I have the following XML document:
<root>
<object type="set">
<name>Test1</name>
<object type="set">
<name>Test11</name>
<object type="set">
<name>Test111</name>
</object>
</object>
</object>
<object type="set">
<name>Test2</name>
<object type="set">
<name>Test22</name>
</object>
</object>
<object type="set">
<name>Test3</name>
</object>
</root>
and the following XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="//object[@type='set']">
<p>
<xsl:value-of select="name"/>
</p>
</xsl:template>
</xsl:stylesheet>
Somehow //object[@type='set'] only selects the first (Test1, Test2开发者_StackOverflow中文版, Test3). But I want to select all elements (Test11, Test111, Test22).
A template is never instantiated "by itself".
Instead, a template is applied only on the node-list that is specified by the expression
on the <xsl:apply-templates select="expression"/>
instruction.
Also note, that
<xsl:template match="//object[@type='set']">
is equivalent to;
<xsl:template match="object[@type='set']">
again -- a template doesnt select it matches.
One solution to this problem:
Use:
<xsl:apply-templates select="//object[@type='set']"/>
The whole transformation becomes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="//object[@type='set']"/>
</body>
</html>
</xsl:template>
<xsl:template match="object[@type='set']">
<p>
<xsl:value-of select="name"/>
</p>
</xsl:template>
</xsl:stylesheet>
and it produces the wanted, correct result:
<html>
<body>
<p>Test1</p>
<p>Test11</p>
<p>Test111</p>
<p>Test2</p>
<p>Test22</p>
<p>Test3</p>
</body>
</html>
Well, additionally, I want to say that your xpath expression indeed matches every object of type set.
But you have to pay attantion to the circumstance that an element "object" of type "set" might contain another element of the very same type. In your transformation script you completely ignore this fact.
You simply copy the value of the first occurence of a attribute "name" and ignoring it's possible children.
A possible solution the way you intended to solve it could be:
<xsl:template match="//object[@type='set']">
<p>
<xsl:value-of select="name"/>
</p>
<xsl:for-each select=".//object[@type='set']">
<p>
<xsl:value-of select="name"/>
</p>
</xsl:for-each></xsl:template>
Instead i would prefer to initialise a variable (nodeset) of your xpath-expression, pass it as parameter to a corrosponding template and iterate via for-each through it.
Hope I could help, and apologyze for my bad english :)
Best Regards
精彩评论