DTD和XMLSchemas的等价性

时间:2009-04-07 06:40:50

标签: xsd dtd

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

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

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

里面的元素&lt;数据&gt;可以按任何顺序出现,每个都是基数0 .. * 使用XMLSchema,如果我使用&lt;定义复杂类型xs:全部&gt;我可以使这些元素无序,但最大基数为1。 xs:sequence&gt;和&lt; xs:choice&gt;是其他明显的候选人,但他们比我想要的更具限制性。

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

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

有没有办法构建一个等效的模式,还是我必须在这里使用DTD?

2 个答案:

答案 0 :(得分:1)

只有保留元素的顺序才能通过XSD实现(因此可以使用 xs:sequence )。我的意思是, float 总是会出现在数组之后(如果有的话),并且 int 总是会出现在 float之后(如果有的话),考虑到你可以按照你想要的每种类型重复多次(或完全省略它们)。

原因是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>

答案 1 :(得分: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的工具更加笨重。