【问题标题】:xs:assert always fails with xerces validation, but works in xmlspyxs:assert 在 xerces 验证时总是失败,但在 xmlspy 中有效
【发布时间】:2020-01-20 17:46:37
【问题描述】:

我正在为我们的 xml 输入/输出设置架构,并且遇到了一个问题,即 XMLSpy 验证正常,但 Xerces 在其中一个 xs:asserts 上失败。 我正在使用最新的 xerces,xerces-2_12_0-xml-schema-1.1。

我已包含该发行版中的所有 .jar 文件(xercesSamples.jar 除外)

测试代码为:

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
factory.setFeature("http://apache.org/xml/features/validation/cta-full-xpath-checking", true);
Schema schema = factory.newSchema(new File("C:/Imports/Test.xsd"));
validator = schema.newValidator();
validator.validate(new StreamSource("C:/Imports/Test.xml"));

我已将 xsd 文件精简为:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:lit="http://www.w3schools.com" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" targetNamespace="http://www.w3schools.com" elementFormDefault="qualified" attributeFormDefault="unqualified" vc:minVersion="1.1">
    <xs:element name="MetrixXML">
        <xs:complexType>
            <xs:all>
                <xs:element ref="lit:Page" minOccurs="1" maxOccurs="unbounded"/>
            </xs:all>
            <xs:attribute name="SchemaVersion" type="xs:float" use="required"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="Page">
        <xs:complexType>
            <xs:attribute name="ContentPositionRule" type="xs:string"/>
            <xs:attribute name="FilePageNum" type="xs:nonNegativeInteger"/>
            <xs:assert test="(//@SchemaVersion ge 2.1) or ((//@SchemaVersion lt 2.1) and not (@ContentPositionRule))"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

xml 是:

<?xml version="1.0" encoding="UTF-8"?>
<MetrixXML xmlns="http://www.w3schools.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com Test.xsd" SchemaVersion="2.1" >
    <Page FilePageNum="1"/>
    <Page ContentPositionRule="CenterEachPage"/>
</MetrixXML>

我得到的错误是:

org.xml.sax.SAXParseException: cvc-assertion: 元素“页面”的断言评估 ('(//@SchemaVersion ge 2.1) 或 ((//@SchemaVersion lt 2.1) 而不是 (@ContentPositionRule))') ' 在架构类型 '#AnonType_Page' 上没有成功。

在 XMLSpy 中,如果我将 SchemaVersion 设置为 2.0,则断言失败。如果我将其设置为 2.1,则断言成功。

我需要设置一些功能标志吗?

更新: 显然 XMLSpy 允许它不应该允许的事情。

因此,所需的测试是 如果(SchemaVersion

【问题讨论】:

  • 在 XMLSpy 中,如果我将 SchemaVersion 设置为 2.0,则断言失败。如果我将其设置为 2.1,则断言成功。 请注意,您可能有一些拼写错误:断言需要 XSD 1.1,而不是 XSD 1.0;目前没有 XSD 2.02.1。有关如何使用 Xerces 针对 XSD 1.1 验证 XML,请参阅重复链接。
  • 请注意,“SchemaVersion”属性与 xsd 无关。这是我们 xml 的私有属性。我已经阅读了引用的问题,但它并不相同,因为 xsd 1.1 有问题,而我的处理 xsd 1.1 - 但 xerces 没有处理更复杂的断言语句。模式工厂被告知使用 xsd 1.1,并且确实如此。它理解断言 - 但似乎没有正确评估它。
  • 对不起,我看错了你的问题。我已经重新打开了。

标签: xsd xsd-validation xerces xpath-2.0 xsd-1.1


【解决方案1】:

将断言在层次结构中上移一级,并确保它仅引用关联元素的后代:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:lit="http://www.w3schools.com"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           targetNamespace="http://www.w3schools.com" 
           elementFormDefault="qualified"
           attributeFormDefault="unqualified" vc:minVersion="1.1">
  <xs:element name="MetrixXML">
    <xs:complexType>
      <xs:all>
        <xs:element ref="lit:Page" minOccurs="1" maxOccurs="unbounded"/>
      </xs:all>
      <xs:attribute name="SchemaVersion" type="xs:float" use="required"/>
      <xs:assert test=" (@SchemaVersion ge 2.1) or 
                       ((@SchemaVersion lt 2.1) and 
                         not (lit:Page/@ContentPositionRule))       
</xs:complexType>
  </xs:element>
  <xs:element name="Page">
    <xs:complexType>
      <xs:attribute name="ContentPositionRule" type="xs:string"/>
      <xs:attribute name="FilePageNum" type="xs:nonNegativeInteger"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

断言只允许引用它出现的元素和该元素的后代——而不是它的祖先、兄弟姐妹等。

另请参阅:

XMLSpy 观察到的行为

尽管在技术上(尽管没有帮助)为断言出现的元素的兄弟姐妹或祖先提供诊断帮助是符合规范的,但 XMLSpy 不应该根据兄弟姐妹或祖先状态报告不同的验证结果。

W3C XML Schema Definition Language (XSD) 1.1 Part 1: Structures

Validation Rule: Assertion Satisfied

[...]

1.3 从“部分”·post-schema-validation 信息集·,一个数据模型实例按照[XDM] 中的描述构建。的根节点 [XDM] 实例由 E 构造;数据模型实例包含 只有那个节点和从 [attributes] 构造的节点, [孩子],以及 E 的后代。注意:这是由此产生的结果 试图在断言中引用兄弟姐妹的构造 或 E 的祖先,或 E 之外的输入文档的任何部分 本身,将不成功。此类尝试引用不在 本身错误,但用于评估它们的数据模型实例 不包括对文件任何部分的任何陈述 在 E 之外,所以它们不能被引用。

注意:这是这种构造的结果,它试图在断言中引用 E 的兄弟姐妹或祖先,或任何 E 本身之外的部分输入文档将不成功。 这种尝试引用本身并不是错误,而是数据 用于评估它们的模型实例不包括任何 表示 E 之外的文档的任何部分,因此它们 无法引用。

[强调。]

【讨论】:

  • 那么,您是说从根目录进行的“//”搜索不应该在断言中工作?另请注意,将断言向上移动 - 意味着它没有要检查的 ContentPositionRule 属性,因此断言始终成功。这也是一个极其简化的示例,因为在真实模式中, 元素出现在层次结构中的多个不同位置。这意味着我需要为每个可能的路径添加另一个断言副本。这使得断言 FAR FAR 不太有用。
  • 不,我的意思是断言应该尝试引用关联元素的兄弟节点或祖先节点。但是,您可以通过.// 相对访问后代,因此,如果我正确理解您的目标,这不应该像您担心的那样令人望而却步。
  • 刚刚花了一些时间尝试变体。这在顶级元素中似乎有效; ...
  • 因此,几乎所有元素之间的验证都需要在顶级元素中。对可维护性不是特别好。
  • 说得太早了。我似乎找不到允许我将对 ContentPositionRule 的检查限制在顶部元素下的“页面”元素的语法变体。
猜你喜欢
  • 1970-01-01
  • 2016-01-18
  • 2016-03-25
  • 2022-01-21
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多