XSD - 验证时忽略属性限制

发布于 2024-10-26 13:53:23 字数 2931 浏览 1 评论 0原文

我在尝试针对下面的 xml 文件测试下面的 xsd 时遇到问题。是我的工具不好,还是我的 xsd 没有以可预测的方式运行?

测试的软件:

  • xmllint(使用 libxml 版本 20707)
  • XML Copy Editor 1.2.0.6

预期结果:

  • test.xml 验证
  • test-bad.xml 由于域标记中的帐户属性格式错误而导致验证失败

观察到的结果: - test.xml 验证 - test-bad.xml 验证

test.xml

<?xml version="1.0" ?>
<!DOCTYPE configuration SYSTEM "configuration.dtd">
<configuration  timestamp="2011-03-23T20:16:57.222" version="2.2" xmlns="http://www.example.com/api/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/api/2.2 configuration.xsd">
    <domain account="4af17ss66f-c841-4b97-a94a-edd7a012176" >
    </domain>
</configuration>

test-bad.xml

<?xml version="1.0" ?>
<!DOCTYPE configuration SYSTEM "configuration.dtd">
<configuration  timestamp="2011-03-23T20:16:57.222" version="2.2" xmlns="http://www.example.com/api/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/api/2.2 configuration.xsd">
    <domain account="totally invalid account" >
    </domain>
</configuration>

配置.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/api/2.2" elementFormDefault="qualified" version="1.0" xml:lang="EN" targetNamespace="http://www.example.com/api/2.2">
  <xs:element name="configuration">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="domain"/>
      </xs:sequence>
      <xs:attribute name="timestamp" type="xs:normalizedString" use="optional"/>
      <xs:attribute name="version" type="xs:token" fixed="2.2"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="domain">
    <xs:complexType>
      <xs:sequence>
        <xs:any minOccurs="0"/>
      </xs:sequence>
      <xs:attribute name="account" type="uid" use="required">
        </xs:attribute>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="uid">
    <xs:restriction base="xs:string">
      <xs:length value="36"/>
      <xs:pattern value="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

配置.dtd

<!ELEMENT configuration (domain)>
<!ATTLIST configuration
            timestamp           CDATA #IMPLIED
            version             CDATA #FIXED "2.2"
            xmlns               CDATA #IMPLIED
            xmlns:xsi           CDATA #IMPLIED
            xsi:schemaLocation  CDATA #IMPLIED>
<!ELEMENT domain ANY>
<!ATTLIST domain account CDATA #IMPLIED>

I am having issues trying to test the below xsd against the below xml files. Are my tools bad, or is my xsd not functioning in a predictable way?

Software tested:

  • xmllint (using libxml version 20707)
  • XML Copy Editor 1.2.0.6

Expected results:

  • test.xml validates
  • test-bad.xml fails validation due to malformed account attribute in domain tag

Oberved results:
- test.xml validates
- test-bad.xml validates

test.xml

<?xml version="1.0" ?>
<!DOCTYPE configuration SYSTEM "configuration.dtd">
<configuration  timestamp="2011-03-23T20:16:57.222" version="2.2" xmlns="http://www.example.com/api/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/api/2.2 configuration.xsd">
    <domain account="4af17ss66f-c841-4b97-a94a-edd7a012176" >
    </domain>
</configuration>

test-bad.xml

<?xml version="1.0" ?>
<!DOCTYPE configuration SYSTEM "configuration.dtd">
<configuration  timestamp="2011-03-23T20:16:57.222" version="2.2" xmlns="http://www.example.com/api/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/api/2.2 configuration.xsd">
    <domain account="totally invalid account" >
    </domain>
</configuration>

configuration.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/api/2.2" elementFormDefault="qualified" version="1.0" xml:lang="EN" targetNamespace="http://www.example.com/api/2.2">
  <xs:element name="configuration">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="domain"/>
      </xs:sequence>
      <xs:attribute name="timestamp" type="xs:normalizedString" use="optional"/>
      <xs:attribute name="version" type="xs:token" fixed="2.2"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="domain">
    <xs:complexType>
      <xs:sequence>
        <xs:any minOccurs="0"/>
      </xs:sequence>
      <xs:attribute name="account" type="uid" use="required">
        </xs:attribute>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="uid">
    <xs:restriction base="xs:string">
      <xs:length value="36"/>
      <xs:pattern value="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

configuration.dtd

<!ELEMENT configuration (domain)>
<!ATTLIST configuration
            timestamp           CDATA #IMPLIED
            version             CDATA #FIXED "2.2"
            xmlns               CDATA #IMPLIED
            xmlns:xsi           CDATA #IMPLIED
            xsi:schemaLocation  CDATA #IMPLIED>
<!ELEMENT domain ANY>
<!ATTLIST domain account CDATA #IMPLIED>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梓梦 2024-11-02 13:53:23

问题是您不小心定义了两个名为“domain”的不同元素

这定义了一个,它只能出现在 configuration 内部:

    <xs:element name="domain"/>

这定义了另一个,它只能作为根元素出现(如果删除 configuration 元素,您可以看到这一点)并将 domain 作为根 - 它将不再验证):

<xs:element name="domain">
  <xs:complexType>
    <xs:sequence>
      <xs:any minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="account" type="uid" use="required">
      </xs:attribute>
  </xs:complexType>
</xs:element>

由于第一个定义没有说明其属性,因此在您的示例文档中,您的 domain 上的属性“account” 元素对任何类型都有效。

要仅定义一个元素,最好的方法是将您拥有的 element 定义放入 complexType 中,并引用它(另一种选择是移动所有 element第一个 domain 定义中的 >complexType 内容):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/api/2.2" elementFormDefault="qualified" version="1.0" xml:lang="EN" targetNamespace="http://www.example.com/api/2.2">
  <xs:element name="configuration">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="domain" type="domain"/> <!-- changed here -->
      </xs:sequence>
      <xs:attribute name="timestamp" type="xs:normalizedString" use="optional"/>
      <xs:attribute name="version" type="xs:token" fixed="2.2"/>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="domain"> <!-- and here -->
    <xs:sequence>
      <xs:any minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="account" type="uid" use="required">
      </xs:attribute>
  </xs:complexType>

  <xs:simpleType name="uid">
    <xs:restriction base="xs:string">
      <xs:length value="36"/>
      <xs:pattern value="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

The problem is you've accidentally defined two different elements with the name "domain".

This defines one, which can occur only inside configuration:

    <xs:element name="domain"/>

And this defines the other, which can only occur as a root element (you can see this if you remove the configuration element and have domain as the root - it won't validate anymore):

<xs:element name="domain">
  <xs:complexType>
    <xs:sequence>
      <xs:any minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="account" type="uid" use="required">
      </xs:attribute>
  </xs:complexType>
</xs:element>

Since the first definition doesn't say anything about its attributes, in your sample document the attribute "account" on your domain element is valid with any type.

To define only one element, the best way is to make the element definition you have into a complexType, and refer to that (the other alternative is to move all the complexType stuff inside the first domain deinfition):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/api/2.2" elementFormDefault="qualified" version="1.0" xml:lang="EN" targetNamespace="http://www.example.com/api/2.2">
  <xs:element name="configuration">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="domain" type="domain"/> <!-- changed here -->
      </xs:sequence>
      <xs:attribute name="timestamp" type="xs:normalizedString" use="optional"/>
      <xs:attribute name="version" type="xs:token" fixed="2.2"/>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="domain"> <!-- and here -->
    <xs:sequence>
      <xs:any minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="account" type="uid" use="required">
      </xs:attribute>
  </xs:complexType>

  <xs:simpleType name="uid">
    <xs:restriction base="xs:string">
      <xs:length value="36"/>
      <xs:pattern value="[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文