xslt调用模板不符合我的预期

时间:2017-06-01 14:56:23

标签: xml xslt xslt-1.0

我错过了什么概念,因为我没有得到我所期待的东西?另外,为什么@field在第二次匹配时会空白(不显示' location')?

xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output method="text"/>

  <!-- sample XSLT snippet -->
  <xsl:template match="xml">
    <xsl:apply-templates select="*" />
    <!-- three nodes selected here -->
    <xsl:call-template name="rshandle" />

  </xsl:template>

  <xsl:template match="foo">
    <!-- will be called once -->
    <xsl:text>
      foo element encountered
    </xsl:text>
  </xsl:template>

  <xsl:template match="*">
    <!-- will be called twice -->
    <xsl:text>
      other element ecountered
    </xsl:text>
  </xsl:template>


  <xsl:template name="rshandle" match="foo">
    <!-- will be called once -->
    <xsl:value-of select="@field" />
    <xsl:text>
      oops i did it again!
    </xsl:text>
  </xsl:template>

</xsl:stylesheet>  

xml

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="calltemplatematch.xslt"?>
<!-- sample XML snippet -->
<xml>
  <foo field="location"/>
  <bar />
  <baz />
</xml>

期待

      other element ecountered

      other element ecountered

location
      oops i did it again!

实际

location
      oops i did it again!

      other element ecountered

      other element ecountered

      oops i did it again!

2 个答案:

答案 0 :(得分:1)

  

为什么在底部出现的第二个实例上@field为空?

因为当&#34; rshandle&#34;模板称为,它是从xml根元素的上下文调用的 - 它没有field属性。 调用模板不会更改当前上下文 - 与应用模板不同。

答案 1 :(得分:1)

为了满足您的期望,XSL应如下所示:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="text"/>

    <!-- sample XSLT snippet -->
    <xsl:template match="xml">
        <xsl:apply-templates select="*"/>
        <!-- three nodes selected here -->
        <xsl:apply-templates select="foo" mode="rshandle"/>
    </xsl:template>

    <xsl:template match="foo"/>

    <xsl:template match="*">
        <!-- will be called twice -->
        <xsl:text>other element ecountered</xsl:text>
    </xsl:template>

    <xsl:template match="foo" mode="rshandle">
        <!-- will be called once -->
        <xsl:value-of select="@field"/>
        <xsl:text>oops i did it again!</xsl:text>
    </xsl:template>

</xsl:stylesheet>
  

另外,为什么在匹配第二次时@field是空白的(不显示'位置')?

因为您使用了<xsl:call-template>。来自another answer的好解释:

  

使用XSLT理解的概念是“当前节点”。使用<xsl:apply-templates>时,当前节点会在每次迭代时继续运行,而<xsl:call-template>不会更改当前节点。即被调用模板中的.指的是与调用模板中的.相同的节点。 apply-templates不是这种情况。