Reputation: 15
This is my xml:
<volume>
<cap>title 1</cap>
<cap>title 2</cap>
<cap>title 3</cap>
<cap>title 4</cap>
<cap>title 5</cap>
<desc>desc 1</desc>
<desc>desc 2</desc>
<desc>desc 3</desc>
<desc>desc 4</desc>
<desc>desc 5</desc>
</volume>
I want to convert it usign xslt, the final result shoudl be this:
<table>
<tr>
<td>title 1</td>
<td>desc 1</td>
</tr>
<tr>
<td>title 2</td>
<td>desc 2</td>
</tr>
<tr>
...
</tr>
I have tryed this xslt code:
...
<table style="border:solid 1px; width:500px; margin:auto;">
<xsl:for-each select="cap">
<tr>
<td style="border-top: dotted 1px; border-right:solid 1px; text-align:right; width:46%;">
<xsl:value-of select="."/>
<br/>
</td>
<td style="border-top: dotted 1px; text-align:right; :46%;">
<xsl:value-of select="../desc[position()]"/>
<br/>
</td>
</tr>
</xsl:for-each>
</table>
...
but it doesn't work. Which is the correct way to get the n-th desc when i'm in the n-th cap?
Upvotes: 1
Views: 42
Reputation: 57169
Thanks for the update to your question.
<xsl:value-of select="../desc[position()]"/>
Your idea is correct, except that position()
here takes the position of desc
, which is 1, 2, 3 etc, depending on the position of desc
(the focus changes on each predicate test). A test like that is always true, because if the predicate contains a numeric value $X
, it is short for $X = position()
. In this case, you are actually writing ../desc[position() = position()]
, which is always true.
What you want is the current position of cap
. To fix this, use a variable, as can be seen below.
Here's how I would do it, using XSLT's power with template matching:
<xsl:output indent="yes" method="html" />
<xsl:attribute-set name="td1">
<xsl:attribute name="style">border-top: dotted 1px; border-right:solid 1px; text-align:right; width:46%;</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="td2">
<xsl:attribute name="style">border-top: dotted 1px; text-align:right; :46%;</xsl:attribute>
</xsl:attribute-set>
<xsl:template match="/volume">
<table style="border:solid 1px; width:500px; margin:auto;">
<xsl:apply-templates select="cap" />
</table>
</xsl:template>
<xsl:template match="cap">
<tr>
<xsl:variable name="pos" select="position()" />
<td xsl:use-attribute-sets="td1">
<xsl:value-of select="." />
<br />
</td>
<xsl:apply-templates select="../desc[$pos]" />
</tr>
</xsl:template>
<xsl:template match="desc">
<td xsl:use-attribute-sets="td2">
<xsl:value-of select="." />
<br />
</td>
</xsl:template>
EDIT: after your update of your question, I added the dealings with the style attribute, and appended the <tr>
element. Result is now, given your input:
<table style="border:solid 1px; width:500px; margin:auto;">
<tr>
<td style="border-top: dotted 1px; border-right:solid 1px; text-align:right; width:46%;">title 1<br></td>
<td style="border-top: dotted 1px; text-align:right; :46%;">desc 1<br></td>
</tr>
<tr>
<td style="border-top: dotted 1px; border-right:solid 1px; text-align:right; width:46%;">title 2<br></td>
<td style="border-top: dotted 1px; text-align:right; :46%;">desc 2<br></td>
</tr>
<tr>
<td style="border-top: dotted 1px; border-right:solid 1px; text-align:right; width:46%;">title 3<br></td>
<td style="border-top: dotted 1px; text-align:right; :46%;">desc 3<br></td>
</tr>
<tr>
<td style="border-top: dotted 1px; border-right:solid 1px; text-align:right; width:46%;">title 4<br></td>
<td style="border-top: dotted 1px; text-align:right; :46%;">desc 4<br></td>
</tr>
<tr>
<td style="border-top: dotted 1px; border-right:solid 1px; text-align:right; width:46%;">title 5<br></td>
<td style="border-top: dotted 1px; text-align:right; :46%;">desc 5<br></td>
</tr>
</table>
Upvotes: 1