当存在属性数据时,为什么xpath不会拾取节点?

时间:2013-01-17 16:59:09

标签: xml xslt xslt-2.0

任何人都可以向我解释为什么以下xslt:

<xsl:if test="EventDocument">

不接受此xml标记吗?

<EventDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.itron.com/ItronInternalXsd/1.0/">

当我从标签中删除属性时它起作用,这对我来说没有意义。

即。当我将输入修改为:

时,上述测试通过
<EventDocument>

我正在使用xslt 2.0(撒克逊语解析器)提前谢谢

2 个答案:

答案 0 :(得分:2)

xmlns是“保留属性” - 它是名称空间前缀到完整节点名称空间的映射的定义。在What does "xmlns" in XML mean?

中详细介绍

即。您的案例中节点的实际名称是"http://www.itron.com/ItronInternalXsd/1.0/" EventDocument,但您尝试选择"" EventDocument(名称为“EventDocument”的节点和空名称空间)。

根据您的XPath引擎,您需要

  • 将名称空间前缀映射到名称空间
  • 使用显式匹配命名空间和节点名称。 *[namespace-uri()="http://www.itron.com/ItronInternalXsd/1.0/" and local-name()=="EventDocument"]
  • 作弊并只匹配节点名称*[local-name()=="EventDocument"]

http://www.w3.org/TR/xpath/#section-Node-Set-Functions中涵盖local-namenamespace-uri)。

答案 1 :(得分:2)

默认情况下,XPath表达式中未加前缀的元素名称引用带有 no namespace 的元素,因此表达式EventDocument选择具有本地名称“EventDocument”且没有名称空间的元素。

<EventDocument ... xmlns="http://www.itron.com/ItronInternalXsd/1.0/">

元素与此模式不匹配,因为它位于http://www.itron.com/ItronInternalXsd/1.0/命名空间中。

你有两个选择,

  1. 将该命名空间绑定到样式表中的前缀,然后在XPath表达式中使用前缀,或
  2. (因为您说您使用的是XSLT 2.0)使用xpath-default-namespace
  3. 1的例子

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
           xmlns:itron="http://www.itron.com/ItronInternalXsd/1.0/"
           version="2.0">
    
      <xsl:template match="itron:example">
        <xsl:if test="itron:EventDocument">....</xsl:if>
      </xsl:template>
    </xsl:stylesheet>
    

    2的例子

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
           xpath-default-namespace="http://www.itron.com/ItronInternalXsd/1.0/"
           version="2.0">
    
      <xsl:template match="example">
        <xsl:if test="EventDocument">....</xsl:if>
      </xsl:template>
    </xsl:stylesheet>
    

    我个人的偏好是关于选项1,对于任何必须在未来维护样式表的人(包括原作者,在几个月休息后回到代码中)的“最小意外原则”基础...