Schematron中的XPath:如何确定节点上是否存在xmlns属性

wol*_*son 3 xml xpath schematron

我正在尝试匹配缺少xmlns属性的特定元素的任何实例,但是我无法获得与语法匹配的问题.我的xml如下所示:

<root>
<node xmlns:m="http://google.com"/>
<node style="block"/>
</root>
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*ler 6

是否需要使用XPath匹配/解析xmlns属性所需的某种限制或语法怪癖?

是的,有点.怪癖是这样的

xmlns:m="..."
Run Code Online (Sandbox Code Playgroud)

语法上属性,但提供比属性更具体的角色.它们是名称空间声明,用于将前缀绑定到名称空间URI.然后可以使用前缀来限定元素和属性名称.还有一个未绑定到前缀的默认命名空间.

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

一旦XML解析器处理了XML文档,名称空间和属性就是可以使用XPath轴访问的不同类型的节点.我不确定我理解为什么要这样做,但您可以使用namespace::轴报告命名空间节点:

namespace::*[not(. = 'http://www.w3.org/XML/1998/namespace')]
Run Code Online (Sandbox Code Playgroud)

您必须小心并排除预定义的名称空间URI

http://www.w3.org/XML/1998/namespace
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

您显示的文档对此SCH文件无效,Schematron验证器将指向node带有命名空间声明的元素:

<node xmlns:m="http://google.com"/>
Run Code Online (Sandbox Code Playgroud)

作为错误的来源.


请注意

namespace::*轴线选择命名空间节点,而不是命名空间声明.由于名称空间由范围内的所有元素继承,因此不仅是声明名称空间具有名称空间节点的元素.它的所有后代也将有一个名称空间节点:

<root>
  <node xmlns:m="http://google.com">
    <descendant_element_with_namespace_node/>
  </node>
  <node style="block"/>
</root>
Run Code Online (Sandbox Code Playgroud)

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