XML 的 XSD 验证失败

Posted

技术标签:

【中文标题】XML 的 XSD 验证失败【英文标题】:XSD verification for XML fails 【发布时间】:2019-05-18 13:07:52 【问题描述】:

我有一个 XML 文件,其内容如下

<?xml version="1.0" encoding="UTF-8"?>
<SETTINGS Version="1">
<CLEANING amount="40"/>
<CLEANING name="abcd"/>
<CLEANING initials="ABCD"/>
<MAINTENANCE state="on"/>
<MAINTENANCE temperature="F"/>
</SETTINGS>

我使用一些生成以下 XSD 输出的工具为此 XML 创建了 XSD 架构。

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="SETTINGS">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="CLEANING" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:attribute name="amount" type="xs:unsignedByte" use="required" />
                        <xs:attribute name="name" type="xs:string" use="required" />
                        <xs:attribute name="initials" type="xs:string" use="required" />
                    </xs:complexType>
                </xs:element>
                <xs:element name="MAINTENANCE" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:attribute name="state" type="xs:string" use="required" />
                        <xs:attribute name="temperature" type="xs:string" use="required" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="Version" type="xs:unsignedByte" use="required" />
        </xs:complexType>
    </xs:element>
</xs:schema>

现在,当我尝试根据生成的 XSD 架构验证此 XMl 时,我得到以下验证错误(使用某些在线验证器验证)。

Not valid.
Error - Line 3, 24: org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 24; cvc-complex-type.4: Attribute 'name' must appear on element 'CLEANING'.
Error - Line 3, 24: org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 24; cvc-complex-type.4: Attribute 'initials' must appear on element 'CLEANING'.
Error - Line 4, 24: org.xml.sax.SAXParseException; lineNumber: 4; columnNumber: 24; cvc-complex-type.4: Attribute 'amount' must appear on element 'CLEANING'.
Error - Line 4, 24: org.xml.sax.SAXParseException; lineNumber: 4; columnNumber: 24; cvc-complex-type.4: Attribute 'initials' must appear on element 'CLEANING'.
Error - Line 5, 28: org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 28; cvc-complex-type.4: Attribute 'amount' must appear on element 'CLEANING'.
Error - Line 5, 28: org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 28; cvc-complex-type.4: Attribute 'name' must appear on element 'CLEANING'.
Error - Line 6, 26: org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 26; cvc-complex-type.4: Attribute 'temperature' must appear on element 'MAINTENANCE'.
Error - Line 7, 31: org.xml.sax.SAXParseException; lineNumber: 7; columnNumber: 31; cvc-complex-type.4: Attribute 'state' must appear on element 'MAINTENANCE'.

XML 和 XSD 都是经过在线验证的有效格式。我无法理解此错误背后的原因。我怀疑这是因为有多个元素共享相同的名称,我认为在生成 XSD 模式时存在一些限制。不知道到底出了什么问题。

我在这里做错了什么,有什么办法可以解决这个错误?

【问题讨论】:

【参考方案1】:
<xs:complexType>
  <xs:attribute name="amount" type="xs:unsignedByte" use="required" />
  <xs:attribute name="name" type="xs:string" use="required" />
  <xs:attribute name="initials" type="xs:string" use="required" />
</xs:complexType>

单词require 表示需要该属性,因此您的XML 的正确书写是:

<CLEANING amount="40" name="abcd" initials="ABCD"/>

如果你想让你写你需要删除你的 XSD 的require

维护也是如此

您的 XSD 验证此文本:

<SETTINGS Version="1">
    <CLEANING amount="40" name="abcd" initials="ABCD"/>
    <MAINTENANCE state="on" temperature="F"/>
</SETTINGS>

但是如果你想用这种外观来验证你的 XML 是不可能把use=require 所以你会有类似的东西:

 ...
    <xs:complexType>
        <xs:attribute name="amount" type="xs:unsignedByte" />
        <xs:attribute name="name" type="xs:string" />
        <xs:attribute name="initials" type="xs:string" />
    </xs:complexType>
...

此外,如果你想拥有你的表格(所以&lt;a att1 ="" /&gt; &lt;a att2="" /&gt;

你需要像这样改变你的属性:

<SETTINGS Version="1">
    <A amount="40" />
    <B name="abcd" />
    <C initials="ABCD"/>
    <D state="on" />
    <E temperature="F"/>
</SETTINGS>

但我认为最后一种可能性可能比第一种选择有点过分

【讨论】:

Charles 是正确的,XSD 规定了CLEANING 的每个元素,可以有多个(maxOccurs=unbounded)需要所有的属性。您将不得不更改 XML 或 XSD 以使它们一起验证。是的,XSD 本身是有效的,XML 也是如此,但是 XML 不遵守此 XSD 设置的特定规则,只遵守一般 XML 规则。 我在这里有一个疑问@charles, 意思相同。我的意思是,如果我们使用第一个版本,如果我们将 xml 更改为第二种方式,代码是否能够以相同的方式解析和提取属性值。解析新的 XML 是否需要任何代码更改。 如果我没有在 XSD 中为某个属性添加 use="required" 并且我的 XML 也不包含该属性,它将导致成功验证,但是在我的情况下,所有这些属性都需要出现在 XML 中。 这取决于你想要什么@Viki。在你的设置中,你只有一个不同的属性和三种情况,所以写&lt;att a="" b="" c="" /&gt;is different than &lt;att a="" /&gt; &lt;att b="" /&gt; &lt;att c="" /&gt; 在第一种情况下,你在一个集团中拥有你所需要的一切。在另一边,你们都分裂了。事实是,如果您采用第二个选项(因此您删除了 require),您还可以编写 &lt;att a="" /&gt; &lt;att b="" /&gt; &lt;att c="" /&gt;&lt;att a="" /&gt; &lt;att b="" c="" /&gt;&lt;att a="" b="" c="" /&gt;&lt;att a="" /&gt; 例如,我不认为你想要 @charles 我们有使用上述格式的 XML 的遗留代码,现在我们计划编写 XSD 来通过限制 XSD 文件中的属性值来验证 XML 中的模式和内容值。在这种情况下,由于某种原因无法更改 XML 格式。是否不可能编写具有属性值限制的 XSD 架构。根据您的建议,如果我们删除“use=required”,那么它可能会起作用,但在这种情况下,即使 XML 不包含该属性,它也会导致 XML 的成功验证--->

以上是关于XML 的 XSD 验证失败的主要内容,如果未能解决你的问题,请参考以下文章

XML 和 XSD 验证失败:元素同时具有“类型”属性和“匿名类型”子项

XMLDSig X509SerialNumber 太大而不能成为 int,XSD 验证失败

使用 C++ 针对 xsd 验证 xml

如何根据 XSD 模式验证 XML 结构的单个条目

PHP 5.3.3 无法针对嵌套的 XSD 验证 XML

Maven 中的 XML DTD/Schema 验证