我正在尝试匹配缺少 xmlns 属性的特定元素的任何实例,但无法与语法匹配。我的xml如图所示:

<root>
<node xmlns:m="http://google.com"/>
<node style="block"/>
</root>

我想返回第一个节点,而不是第二个。如果我根据第二个节点上显示的样式属性进行匹配,我可以简单地使用 not(@style) 但这不适用于 not(@xmlns:m)。我试图通过搜索具有与 URI 匹配的值的任何属性来规避此问题,但同样,这适用于其他属性,但不适用于 xmlns:m。使用 XPath 匹配/解析 xmlns 属性是否存在某种限制或语法怪癖?

最佳答案



是的,有点。怪癖是这样的事情

xmlns:m="..."

在语法上是属性,但比属性具有更具体的作用。它们是将前缀绑定(bind)到命名空间 URI 的命名空间声明。然后可以使用前缀来限定元素和属性名称。还有一个未绑定(bind)到前缀的默认命名空间。

不可能检测到 namespace 声明,因为 XPath(和 XSLT 和 Schematron)不对实际的 XML 文档进行操作,而是对它们的抽象表示进行操作。在此表示(模型)中,不存在 namespace 声明,但存在间接指向 namespace 声明的 namespace 节点。

一旦 XML 解析器处理了 XML 文档,命名空间和属性就是可以使用 XPath 轴访问的不同类型的节点。我不确定我是否理解您为什么要这样做,但是您可以使用 namespace:: 轴报告命名空间节点:
namespace::*[not(. = 'http://www.w3.org/XML/1998/namespace')]

您必须小心并排除预定义的命名空间 URI
http://www.w3.org/XML/1998/namespace

默认情况下绑定(bind)到 xml: 前缀。

ISO Schematron
<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">

    <sch:pattern>
        <sch:rule context="node">
            <sch:report test="namespace::*[not(. = 'http://www.w3.org/XML/1998/namespace')]">Namespace node found!</sch:report>
        </sch:rule>
    </sch:pattern>

</sch:schema>

您显示的文档对于此 SCH 文件无效,并且 Schematron 验证器将指向带有命名空间声明的 node 元素:
<node xmlns:m="http://google.com"/>

作为错误的来源。

请注意
namespace::* 轴选择命名空间节点,而不是命名空间声明。由于命名空间由作用域内的所有元素继承,因此不仅声明命名空间的元素具有命名空间节点。它的所有后代也将有一个命名空间节点:
<root>
  <node xmlns:m="http://google.com">
    <descendant_element_with_namespace_node/>
  </node>
  <node style="block"/>
</root>

请参阅 LarsH 的答案,了解更复杂的 XPath 表达式,以说明这一事实。

关于xml - Schematron 中的 XPath : How to determine if an xmlns attribute is present on a node,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35467330/

10-12 01:20