XSLT无法为for-each找到XPATH

时间:2016-05-16 14:34:02

标签: xml xslt xpath

我正在尝试调试与xpath相关的问题。我在我的XSLT中创建了一个变量$ MetaData,分配了一个xml文档,但由于某些原因,foreach循环无法找到它的子节点而且我无法进入foreach循环。

XSLT:

<!-- language: lang-xslt -->
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns="http://www.w3.org/TR/xhtml1/strict"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt">

  <xsl:variable name="_MetaData">
    <MetaData>
      <EmployeeId>1233</EmployeeId>
      <EmployeeName>abcd</EmployeeName>
    </MetaData>
  </xsl:variable>
  <xsl:variable name="MetaData" select="msxsl:node-set($_MetaData)"></xsl:variable>

  <xsl:template match="*|@*">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[local-name()='MetaDataTag']">
    <xsl:copy>

      <MetaData VocabularyOwner="acme.com" Vocabulary="MetaData">
        <xsl:for-each select="$MetaData//MetaData/*">
          <xsl:element name="Occurrence">
            <xsl:attribute name="Id">
              <xsl:value-of select="local-name(.)"/>
            </xsl:attribute>
            <xsl:attribute name="Value">
              <xsl:value-of select="string(.)"/>
            </xsl:attribute>
          </xsl:element>
        </xsl:for-each>
      </MetaData>

    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

XML:

<?xml version="1.0" encoding="utf-8" ?>
<Envelope>
  <MetaDataTag />
</Envelope>

如果我删除xmlns xmlns =&#34; http://www.w3.org/TR/xhtml1/strict"命名空间,一切似乎工作正常,我能够进入循环。 我不确定如何在不删除xmlns =&#34; http://www.w3.org/TR/xhtml1/strict"命名空间。

1 个答案:

答案 0 :(得分:1)

如果在XSLT中定义默认命名空间,则变量中的节点将位于该命名空间中。 Xpath没有默认命名空间,因此$MetaData//MetaData/*{http://www.w3.org/TR/xhtml1/strict}MetaData元素节点不匹配。

一种解决方案是使用local-name()忽略名称空间。

`$MetaData//*[local-name() = 'MetaData']/*`

或者您可以为Xpath表达式定义(附加)前缀...

<xsl:stylesheet
  version="1.0"
  xmlns="http://www.w3.org/TR/xhtml1/strict"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xhtml="http://www.w3.org/TR/xhtml1/strict">

  ...
</xsl:stylesheet>

...并在表达式中使用它。

`$MetaData//xhtml:MetaData/*`

但是标签在XHTML命名空间中无效,因此最好在空命名空间中创建数据元素:

<xsl:variable name="_MetaData">
  <MetaData xmlns="">
    <EmployeeId>1233</EmployeeId>
    <EmployeeName>abcd</EmployeeName>
  </MetaData>
</xsl:variable>
<xsl:variable name="MetaData" select="msxsl:node-set($_MetaData)"/>

或者为它们定义一个特定的命名空间......

<xsl:stylesheet
  version="1.0"
  xmlns="http://www.w3.org/TR/xhtml1/strict"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:data="urn:data">

  <xsl:variable name="_MetaData">
    <data:MetaData>
      <data:EmployeeId>1233</data:EmployeeId>
      <data:EmployeeName>abcd</data:EmployeeName>
    </data:MetaData>
  </xsl:variable>
  <xsl:variable name="MetaData" select="msxsl:node-set($_MetaData)"/>
  ...
</xsl:stylesheet>

在表达式中使用:

$MetaData//data:MetaData/*