How can I build value for "for-each" expression in XSLT with help of parameter
I need to navigate through this xml tree.
<publication>
<corporate>
<contentItem>
<metadata>meta</metadata>
<content>html&开发者_高级运维lt;/content>
</contentItem>
<contentItem >
<metadata>meta1</metadata>
<content>html1</content>
</contentItem>
</corporate>
<eurasia-and-africa>
...
</eurasia-and-africa>
<europe>
...
</europe>
</publication>
and convert it to html with this stylesheet
<ul>
<xsl:variable name="itemsNode" select="concat('publicationManifest/',$group,'/contentItem')"></xsl:variable>
<xsl:for-each select="$itemsNode">
<li>
<xsl:value-of select="content"/>
</li>
</xsl:for-each>
</ul>
$group is a parameter with name of group for example "corporate". I have an error with compilation of this stylsheet. SystemID: D:\1\contentsTransform.xslt
Engine name: Saxon6.5.5
Severity: error
Description: The value is not a node-set
Start location: 18:0
What the matter?
In XSLT this can be easily achieved in the following way:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pGroup" select="'corporate'"/>
<xsl:template match="/">
<ol>
<xsl:for-each select="/*/*[name()=$pGroup]/contentItem">
<li>
<xsl:value-of select="content"/>
</li>
</xsl:for-each>
</ol>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document, the wanted result is produced:
<ol>
<li>html</li>
<li>html1</li>
</ol>
Do note the use of the XPath name() function.
You cannot build and evaluate dynamic XPath expressions. And 99.9% of the time, you do not need to. Corollary: if you feel the need to dynamically evaluate XPath, you are very likely doing something wrong.
Declare your $pGroup
parameter:
<xsl:param name="pGroup" select="''" />
…make a template for your document element (<publication>
):
<xsl:template match="publication">
<body>
<!-- select only elements with the right name here -->
<xsl:apply-templates select="*[name() = $pGroup]" />
</body>
</xsl:template>
…and one for arbitrary elements that contain <contentItem>
elements:
<xsl:template match="*[contentItem]">
<ul>
<xsl:apply-templates select="contentItem" />
</ul>
</xsl:template>
…and one for <contentItem>
elements themselves:
<xsl:template match="contentItem">
<li>
<xsl:value-of select="content" />
</ul>
</xsl:template>
Done.
精彩评论