XSL将模板应用于所有元素

时间:2011-09-13 12:50:47

标签: xslt xpath

我有以下XML文档:

<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>

以及以下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>

不知何故//对象[@type ='set']只选择第一个(Test1,Test2,Test3)。但我想选择所有元素(Test11,Test111,Test22)。

2 个答案:

答案 0 :(得分:2)

模板永远不会“自行”实例化。

相反,模板仅应用于expression指令上<xsl:apply-templates select="expression"/>指定的节点列表。

另请注意,

<xsl:template match="//object[@type='set']">

相当于;

<xsl:template match="object[@type='set']">

再次 - 模板不选择 匹配

此问题的一个解决方案

使用:

<xsl:apply-templates select="//object[@type='set']"/>

整个转型变为

<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>

,它会产生想要的正确结果

<html>
   <body>
      <p>Test1</p>
      <p>Test11</p>
      <p>Test111</p>
      <p>Test2</p>
      <p>Test22</p>
      <p>Test3</p>
   </body>
</html>

答案 1 :(得分:1)

另外,我想说你的xpath表达式确实匹配set类型的每个对象。

但是你必须要注意“set”类型的元素“object”可能包含同一类型的另一个元素的情况。在您的转换脚本中,您完全忽略了这一事实。

您只需复制属性“name”的第一个出现的值,并忽略它可能的子项。

您希望解决问题的方法可能是:

<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>

相反,我更喜欢初始化xpath-expression的变量(nodeset),将其作为参数传递给相应的模板,并通过for-each遍历它。

希望我能帮忙,并为我糟糕的英语道歉:)

最好的问候