Jump to content

Table Headings next to Table Data


General_HQ

Recommended Posts

I have an interesting XSL problem that I've been scratching my head on for a little while, and am no closer to solving than I was before. I was hoping for some advise on how to do this.I am trying to take a table stored in XML, and translate it to a table stored in RTF, but the trick is, I want to take the headings of the table and put it next to each column of the data in that column.For example ... I have some XML input that reads something like this:<table> <thead> <tr> <td> <p><strong>Year</strong></p></td> <td> <p><strong>U.S. Population</strong></p></td> <td> <p><strong>Unemployment Percentage</strong></p></td> </tr> </thead> <tr> <td>1929</td> <td>88,010,000</td> <td>3.14</td> </tr> <tr> <td>1930</td> <td>89,550,000</td> <td>8.67</td> </tr></table>And I want to transform it into a table in RTF or HTML so it reads like:Year: 1929 | U.S. Population: 88,010,000 | Unemployment Percentage: 3.14 |Year: 1930 | U.S. Population: 89,550,000 | Unemployment Percentage: 8.67 |My question is not how to do the RTF or HTML formatting for the table, but how in XSL can I grab the table column headers in the <thead> portion of the table, and apply them to the appropriate column of the table data below it?Of course, I need a generic solution that will handle any number of columns and any number of rows, but we can assume that there is one heading row at the top and that heading will apply to all columns below it.Is this possible in XSL? And if so, how?I admit I'm not an XSL expert, but I do understand the basics reasonably well, but I just feel there is some trick that I'm missing to accomplish this task.Thanks.Robert

Link to comment
Share on other sites

Ha. XML which is actually pure XHTML. Nice... anyway, as for your idea, where I live is really late so I'm not much into thinking now, so execuse me, but... try something like absolute paths. If they are not an option, then perhaps something like

<xsl:for-each select="td"><td><xsl:value-of select="../../th/p/strong" />:<xsl:value-of select="." /></td></xsl:for-each>

might do the trick.

Link to comment
Share on other sites

Well, no joy with that idea, at least not yet. I don't understand how the phrase:<xsl:value-of select="../../th/p/strong" />would pick up the heading from the proper column. In fact, I can't seem to get it to pick up anything. The headings are blank.I'm actually trying to translate this data to RTF format, so the output I'm looking fo would be something like:\trowd \intbl Year: 1929 \cell \intbl U.S. Population: 88,010,000 \cell \intbl Unemployment Percentage: 3.14 \cell \row\trowd \intbl Year: 1930 \cell \intbl U.S. Population: 89,550,000 \cell \intbl Unemployment Percentage: 8.67 \cell \rowI don't think I can use absolute paths, because I really don't know how deeply nested in other things the <table> is going to be. I also don't know beforehand how many rows or columns are going to be in a table.Here is what I tried, based on your suggestion. It didn't work. It didn't grab the titles and bring them into the cells of the table. (I added the 'Table:' and 'Table Row.' words in there for debugging purposes, so I could tell when the table itself and each row was detected, planning to remove them once it worked.)

<xsl:template match="//table">\par Table: \par <xsl:for-each select="tr">  Table Row. \trowd <xsl:for-each select="td">    \intbl <xsl:value-of select="../../th/p/strong" />:<xsl:value-of select="." /> \cell  </xsl:for-each> </xsl:for-each> \row </xsl:template>

Link to comment
Share on other sites

The ".." XPath operator is used in relative paths to select something from one level above. So for example:

<xsl:for-each select="td"><td><xsl:value-of select=".."/>:<xsl:value-of select="." /></td></xsl:for-each>

Should display all <tr>s, instead of selecting the <td>s.After reading at each letter of your table header I realized you're using a bit unusual tags for the headers. Table headers in XHTML are usually <th> tags while <td>s are used for body data. Also I didn't noticed the <tr> and <thead> was probably out of my mind too. So the fixed expression that works is this:

<xsl:template match="//table">	<xsl:for-each select="tr">	\trowd  <xsl:for-each select="td"> 	 \intbl 	 <xsl:value-of select="../../thead/tr/td/p/strong" />:<xsl:value-of select="." />  \cell  </xsl:for-each></xsl:for-each>\row</xsl:template>

I did said I wasn't very into thinking though :) .

Link to comment
Share on other sites

ok. We're making progress, but we're still not quite there. But I think we're finally at the stage where my original problem can be clarified.With the code snippet you provided, I ended up with a table that looked like:Year: 1929 | Year: 88,010,000 | Year: 3.14 |Year: 1930 | Year: 89,550,000 | Year: 8.67 |Which brings me back to my comment in my last note about me not understanding how that statement you provided would 'pick up the headings from the proper column'. The emphasis there was meant to be on 'from the proper column', not on 'pick up the heading'. I understand how the '..' operator would select something from one level above, but my question is when I go back down into the <thead>/<tr> level from there, how would I get it to select the proper <td> of data from the row ... that is, to select the "Year" heading when I'm in the first column of data, "U.S. Population" when I'm in the second, and "Unemployment Percentage" when I'm in the third. The code snippet you provided always seems to select the first or default <td> entry.That has actually been my stumbling block all along. My apologies for not making that clear earlier.

Link to comment
Share on other sites

Hmm,This is a funny one. I can see the merits of you xml structure, but I would suggest that you don't use this.I think you need to re-structure your xml so that it reads:

<statistics><statistic>  <year>1999</year>  <population>88,100,000</population>  <unemployment>3.14</unemployment></statistic>...</statistics>

Then use a style sheet which reads these three tags and puts them into a table:

<xsl:template match="statistic" ><table><tr><td> <p><strong>Year:</strong></p></td><td><xsl:value-of select="year" /></td></tr><tr><td> <p><strong>U.S. Population</strong></p></td><td><xsl:value-of select="population" /></td></tr><tr><td> <p><strong>Unemployment Percentage</strong></p></td><td><xsl:value-of select="unemployment" /></td></tr></table>

That's just one way to present the data in a table using XSL. For your purposes where you want to use RTF, you can just substitute the table information for the equivalent RTF text:

\trowd \intbl Year: <xsl:value-of select="year" /> \cell \intbl U.S. Population: <xsl:value-of select ="population" /> \cell \intbl Unemployment Percentage: <xsl:value-of select="unemployment" /> \cell \row

The reason I would do this is that I say XML is supposed to separate data from functionality. XML should only contain data - XSL, CSS or your custom application should act on the data to show it or change it or behave in a particular way - the whole point is that XML is intended to be "independent" of the system that wants to use it.I find if I treat xml in this way, it becomes a easier to maintain because I can modify behaviour without worrying about the data.It would be interesting to see what other people think about this though.:)Dooberry.

Link to comment
Share on other sites

Unfortunately, modifying the XML data structure is not an option. That is outside of my control. The data is coming from an outside source that has already set these standards as to what the data is going to look like, and my task at hand is to make the data understandable.In fact, the data format has been defined by NIMAS ( http://nimas.cast.org/ ) as a definition for storing digital versions of textbooks, and I am attempting to take these textbooks that are created in their format, and present them in a manner that would allow them to be understood if presented verbally, not visually. That is why I have to treat tables in such a non-standard fashion. Tables are easy to understand when you look at them visually, with nice headings at the top and the data lined up in nice columns underneath them, but they are not quite so easy to understand when spoken. I am hoping by taking the table headings and re-reading them along with the table data, they will be more comprehensible to a listener (as opposed to a visual reader).The example I gave of 'Years' and 'US Population' and 'Unemployment Percentage' is just sample data. In fact, I have no idea what kind of data will be in the tables of these books, but the chances of it really being 'Years' and 'US Population' and 'Unemployment Percentage' is pretty much zero. This must be a generic solution for any table of any size that has headings provided for it, and not tied to any particular data structure.

Link to comment
Share on other sites

Yup. I was definetly not thinking. Well, now that we're clear and made it to the final stretch, I think we're there.

<xsl:template match="//table">	<xsl:for-each select="tr">	\trowd  <xsl:for-each select="td">  <xsl:variable name="position" select="position()" />  	\intbl  	<xsl:value-of select="../../thead/tr/td[position()=$position]/p/strong" />:<xsl:value-of select="." />  \cell  </xsl:for-each></xsl:for-each>\row</xsl:template>

This time the position of the current td is placed in a variable. then the value-of selects the td in the header which matches the position of the current td. Should be nifty enough :) .[edit] You're welcome. I have a very decent bag'o'tricks myself, so don't hesitate to ask :) @dooberry you're like my better half bro :blink: . I wish I was better at scripting (though I prefer JavaScript then VBScript, but still), so don't be hard on yourself :) .[/edit]

Edited by boen_robot
Link to comment
Share on other sites

THANK YOU, Boen_Robot ! That did it !I knew there had to be a trick I was missing, and creating and using the variable 'position' was exactly what I was looking for. That has now been added to my admitedly small but growing XSL Bag 'o' tricks.It now works, just as I hoped it would. :) Thanks again.General_HQ

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...