Reputation: 153
So this is what my XML looks like. It's pretty darn simple, just want to lay out a bunch of links to other XML files with different names/titles for each link of course:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="index.xsl"?>
<playToc>
<play>a_and_c.xml</play>
<play>all_well.xml</play>
<play>as_you.xml</play>
<play>com_err.xml</play>
<play>coriolan.xml</play>
<play>cymbelin.xml</play>
<name>Title 1</name>
<name>Title 2</name>
<name>Title 3</name>
<name>Title 4</name>
<name>Title 5</name>
<name>Title 6</name>
</playToc>
Pretty simple, right? And so here is my XSL:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="playToc">
<html>
<body style="text-align:center;">
<xsl:apply-templates select="play"></xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="play">
<xsl:variable name="URL">
<xsl:value-of select="."/>
</xsl:variable>
<xsl:variable name="TITLE">
<xsl:value-of select="../name"/>
</xsl:variable>
<a href="{$URL}"><xsl:value-of select="$TITLE"/></a>
<br />
</xsl:template>
</xsl:stylesheet>
And this is the output:
Title 1
Title 1
Title 1
Title 1
Title 1
Title 1
When I want this to be the output, of course:
Title 1
Title 2
Title 3
Title 4
Title 5
Title 6
Any help would be so great! Thanks a bunch!
Upvotes: 1
Views: 1270
Reputation: 243579
<xsl:variable name="TITLE"> <xsl:value-of select="../name"/> </xsl:variable>
Your problem is here.
The string value of ../name
is the string value of the first name
child of the parent of the initial context (current) node.
What you actually want is to get the value of the name
child that has the same position as the position of the current (play
) node.
This complete and short transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="play">
<xsl:variable name="vPos" select="position()"/>
<a href="{.}">
<xsl:value-of select="../name[$vPos]"/>
</a><br />
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
when applied on the provided source XML document:
<playToc>
<play>a_and_c.xml</play>
<play>all_well.xml</play>
<play>as_you.xml</play>
<play>com_err.xml</play>
<play>coriolan.xml</play>
<play>cymbelin.xml</play>
<name>Title 1</name>
<name>Title 2</name>
<name>Title 3</name>
<name>Title 4</name>
<name>Title 5</name>
<name>Title 6</name>
</playToc>
produces the wanted, correct result:
<a href="a_and_c.xml">Title 1</a>
<br/>
<a href="all_well.xml">Title 2</a>
<br/>
<a href="as_you.xml">Title 3</a>
<br/>
<a href="com_err.xml">Title 4</a>
<br/>
<a href="coriolan.xml">Title 5</a>
<br/>
<a href="cymbelin.xml">Title 6</a>
<br/>
Do note:
There is no need to use xsl:apply-templates
at all.
There is just one template.
Upvotes: 1
Reputation: 167716
Well the XML input is poorly structured but you can work around this by doing
<xsl:template match="play">
<xsl:variable name="pos" select="position()"/>
<a href="{.}">
<xsl:value-of select="../name[position() = $pos]"/>
</a>
<br/>
</xsl:template>
Make sure you keep the <xsl:apply-templates select="play"/>
in the other template, otherwise the approach with position()
won't work.
Upvotes: 2