1

我一直认为 XMLSchema 和 DTD 是等价的,但后者在建模复杂关系(如继承)时使用起来更麻烦。

最近我想构建一个模式来验证具有如下结构的文档:

<data>
 <array>
   <int></int>
   <int></int>
 </array>
 </array>
   <float></float>
   <float></float>
 </array>
 <int><int>
 <float></float>
</data>

<data> 中的元素可以按任何顺序出现,每个元素的基数为 0..* 使用 XMLSchema,如果我使用 <xs:all> 定义复杂类型,我可以让元素乱序,但最大基数为 1。 < xs:sequence > 和 < xs:choice > 是其他明显的候选者,但它们比我想要的更严格。

然后我注意到 DTD 似乎能够像这样实现这一点:

<!ELEMENT data (array | float | int)*>

有什么方法可以构建一个等效的模式,还是我必须在这里使用 DTD?

4

2 回答 2

1

如果您保持元素的顺序,则只能通过 XSD 实现(因此您可以使用xs:sequence)。我的意思是,浮点数总是会出现在数组(如果有)之后,而int总是会出现在浮点数(如果有)之后,考虑到您可以根据需要对每种类型重复尽可能多的事件(或省略他们完全)。

原因是 XSD xs:all复杂类型不支持其任何内容类型(元素、其他嵌套组类型等)的无界属性。其他更“宽松”的模式将允许您这样做,例如您所说的 DTD,或例如 RelaxNG。

这是适合您的 XML 文件的示例 XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:complexType name="arrayType">
            <xs:sequence>
                <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
                <xs:element name="int" minOccurs="0" maxOccurs="unbounded"/>
                <xs:element name="float" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
    </xs:complexType>
    <xs:element name="data" type="arrayType"/>
</xs:schema>
于 2009-04-07T07:32:54.587 回答
0

我想我会回到这个,因为之前的答案是不正确的。事实上,使用 XML Schema 可以解决原来的问题。

正确的方法是定义一个组元素,它包含所有各种选项(整数、浮点数、数组)之间的选择,并且每个选项的基数为 0..*。

<xs:group name="dataTypesGroup">
    <xs:choice>
        <xs:element name="int" type="intType"/>
        <xs:element name="float" type="floatType"/>
        <xs:element name="array">
            <xs:complexType>
                <xs:choice>
                    <xs:element name="int" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="float" type="xs:float" minOccurs="0" maxOccurs="unbounded"/>
                </xs:choice>
                <xs:attribute name="id" use="required"></xs:attribute>
            </xs:complexType>    
        </xs:element>
    </xs:choice>
</xs:group>

从这里开始,仍然需要在 complexType 定义中引用组并将组的基数设置为 0..*

<xs:element name="data" minOccurs="0" maxOccurs="unbounded">
    <xs:complexType>
        <xs:group ref="dataTypesGroup" minOccurs="0" maxOccurs="unbounded"/>
    </xs:complexType>
</xs:element>

等等。有点冗长(尤其是与 RelaxNG 的语法相比),但好处是 XML Schema 得到了更好的支持。我已经制作了一个基于 RelaxNG 的解析器来解决原始问题,但是可用的验证器(如 JING)比使用 Java 等附带的基于 XML Schema 的工具要笨重得多。

于 2009-04-24T01:21:17.823 回答