c# - 对错误消息 "invalid XPath for selector or field"感到困惑

标签 c# xml xpath xsd

我试图更好地理解 key 和 keyref 以及如何在模式中使用它们。我想将 key 应用于 y 类型的部分,但不应用于 z 类型的部分。我很困惑为什么会看到以下错误。

'r:B/r:part[@type='y']' is an invalid XPath for selector or field

我几乎确信 XPath 是有效的,但是当我在 XPath 表达式中输入谓词过滤器时,我就从 Visual Studio 中收到错误。

这是 XML

<root xmlns="namespace1">
  <A>
    <!-- if the ref-number is not equal to one of the key-number, the validation will give error -->
    <part ref-number="1"/>
  </A>
  <A>
    <!-- if the ref-number is not equal to one of the key-number, the validation will give error -->
    <part ref-number="2"/>
  </A>
  <B>
    <part type="y" key-number="1"/>
    <part type="y" key-number="2"/>
    <part type="z" key-number="3"/>
  </B>
</root>

这是架构

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="namespace1" xmlns:r="namespace1" elementFormDefault="qualified">
      <xs:element name="root">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="A" type="r:aType" maxOccurs="unbounded">
              <xs:keyref name="dummy" refer="r:partNumberKey">
                <xs:selector xpath="r:part"/>
                <xs:field xpath="@ref-number"/>
              </xs:keyref>
            </xs:element>
            <xs:element name="B" type="r:bType"/>
          </xs:sequence>
        </xs:complexType>
        <xs:key name="partNumberKey">
<!-- I get an error here -->
          <xs:selector xpath="r:B/r:part[@type='y']"/>
          <xs:field xpath="@key-number"/>
        </xs:key>
      </xs:element>
      <xs:complexType name="aType">
        <xs:sequence>
          <xs:element name="part" maxOccurs="unbounded">
            <xs:complexType>
              <xs:simpleContent>
                <xs:extension base="xs:string">
                  <xs:attribute name="ref-number" type="xs:integer"/>
                </xs:extension>
              </xs:simpleContent>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="bType">
        <xs:sequence>
          <xs:element name="part" maxOccurs="unbounded">
            <xs:complexType>
              <xs:simpleContent>
                <xs:extension base="xs:string">
                  <xs:attribute name="key-number" type="xs:integer"/>
                  <xs:attribute name="type" type="xs:string"/>
                </xs:extension>
              </xs:simpleContent>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
    </xs:schema>

最佳答案

您从 Xerces/Oxygen 收到更有意义的错误消息:

[Xerces] c-general-xpath: The expression 'r:B/r:part[@type='y']' is not valid with respect to the XPath subset supported by XML Schema.

XML 架构仅支持 subset of XPath 。以下规则列出了允许作为 xs:selectorxpath 属性值的内容:

[1]     Selector       ::=      Path ( '|' Path )*
[2]     Path       ::=      ('.//')? Step ( '/' Step )*
[3]     Step       ::=      '.' | NameTest
[4]     NameTest       ::=      QName | '*' | NCName ':' '*'

这是一种隐晦的说法,表示在此上下文中不支持带有谓词的表达式(在 [] 之间)。

如果您自己设计了此 XML,则可以为 part 元素指定不同的名称,而不是不同的 type 属性。


另一种方法是在执行此检查的 XML 架构中包含 Schematron 规则。

使用嵌入式 Schematron 修改 XML 架构

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:r="namespace1"
    xmlns:sch="http://purl.oclc.org/dsdl/schematron"
    targetNamespace="namespace1"
    elementFormDefault="qualified">

    <xs:annotation>
        <xs:appinfo>
            <sch:ns uri="namespace1"
                prefix="r" />
            <sch:pattern>
                <sch:rule context="r:A/r:part">
                    <sch:assert test="@ref-number = /r:root/r:B/r:part/@key-number">Key Error!</sch:assert>
                </sch:rule>
            </sch:pattern>
        </xs:appinfo>
    </xs:annotation>

    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="A" type="r:aType" maxOccurs="unbounded"/>
                <xs:element name="B" type="r:bType"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="aType">
        <xs:sequence>
            <xs:element name="part" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:simpleContent>
                        <xs:extension base="xs:string">
                            <xs:attribute name="ref-number" type="xs:integer"/>
                        </xs:extension>
                    </xs:simpleContent>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="bType">
        <xs:sequence>
            <xs:element name="part" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:simpleContent>
                        <xs:extension base="xs:string">
                            <xs:attribute name="key-number" type="xs:integer"/>
                            <xs:attribute name="type" type="xs:string"/>
                        </xs:extension>
                    </xs:simpleContent>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

我不确定这是否正是您想要的,因为我没有完全理解为什么 part 元素的 type 属性很重要。

如果您在 XML 实例文档中引用 XSD,您现在还需要包含 Schematron 规则的引用,类似于

<?xml-model href="../Desktop/key.xsd" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>

关于c# - 对错误消息 "invalid XPath for selector or field"感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35605267/

相关文章:

xml - RDF Schema - 如何创建实例?

XPATH 过滤无标签子项

c# - 通过网络代理使用 Azure KeyVault 配置提供程序会引发 HTTP 407 异常

c# - 如果程序集在 GAC 中,它调用的所有程序集是否也必须在 GAC 中?

c - 在 C 中打印 XML 中的节点

java - 使用 apache commons 配置 xpath 查询具有属性的空 XML 元素

java - 如何在 Sonar 上使用自定义java规则?

c# - 如何为 Office 加载项创建静默安装程序

c# - 关闭非按钮弹出窗口?

java - 在 Android/Java 中更改 XML 值