Reputation: 547
I'm using XSLT 1.0 to process a xml document which has the following sample structure:
<root>
<descriptions>
<description name="abc">
<detail>XXXXXXXXXXXXX</detail>
</description>
<description name="def">
<detail>XXXXXXXXXXXXX</detail>
</description>
<description name="ghi">
<detail>XXXXXXXXXXXXX</detail>
</description>
<description name="lmn">
<detail>XXXXXXXXXXXXX</detail>
</description>
// ....... several more description elements
</descriptions>
<list>
<book name="abc"/>
<book name="def"/>
<book name="lmn"/>
</list>
</root>
I was hoping to match the 'book' under 'list' node with the 'description' under 'descriptions' using the 'name' attribute. So the output would be like:
abc
XXXXXXXXXXXXX
def
XXXXXXXXXXXXX
lmn
XXXXXXXXXXXXX
I tried:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:for-each select="root/list/book">
<xsl:param name="bookName" select="@name"/>
<xsl:for-each select="root/descriptions/description">
<xsl:if test="$bookName = @name">
<h3><xsl:value-of select="$bookName"/></h3>
<p><xsl:value-of select="detail"/></p>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:stylesheet>
I think there must be a more efficient way to achieve this than using nested for-each, but I couldn't think of one..So could anyone give me some help? Thank you!!
Upvotes: 2
Views: 95
Reputation: 28014
You could use a predicate, which is more concise and probably more efficient (depending on your XSLT processor):
<xsl:for-each select="root/list/book">
<xsl:param name="bookName" select="@name"/>
<xsl:variable name="desc"
select="/root/descriptions/description[@name = $bookName]" />
<h3><xsl:value-of select="$bookName"/></h3>
<p><xsl:value-of select="$desc/detail"/></p>
</xsl:for-each>
For a probably greater efficiency improvement, use a key. E.g. put this declaration after <xsl:output>
:
<xsl:key name="descriptions-by-name" match="description" use="@name" />
Then change the <xsl:variable>
select
attribute to use the key:
<xsl:variable name="desc"
select="key('descriptions-by-name', $bookName)" />
Upvotes: 2