XML Schema:任何顺序的元素,发生0-1次或0- *次

时间:2017-07-09 10:11:24

标签: xml validation xsd

我正在开发一个描述消息结构的XML Schema(message.xsd)。

以下是<message>元素(根)的预期子元素:

  • <from>:包含发件人的地址。发生0或1次。
  • <to>:包含收件人的地址。发生0次或更多次。
  • <cc>:包含副本中收件人的地址。发生0次或更多次。
  • <subject>:包含邮件的主题。发生0或1次。
  • <body>:包含邮件正文。发生0或1次。

元素的顺序无关紧要,这意味着它们可以按任何顺序排列。

这是第一个简单的XML示例(message-1.xml)必须有效:

$ xmllint --schema message.xsd message-1.xml 
<?xml version="1.0"?>
<message xmlns="http://yugiohjcj.1s.fr/message">
    <from>me@domain.com</from>
    <to>you@domain.com</to>
    <subject>How are you?</subject>
    <body>Hello. How are you? Thank you. Best regards.</body>
</message>
message-1.xml validates

它有效!

这是第二个更复杂的XML示例(message-2.xml)必须有效:

$ xmllint --schema message.xsd message-2.xml 
<?xml version="1.0"?>
<message xmlns="http://yugiohjcj.1s.fr/message">
    <subject>How are you?</subject>
    <body>Hello. How are you? Thank you. Best regards.</body>
    <from>me@domain.com</from>
    <to>you@domain.com</to>
    <to>and-you@domain.com</to>
    <cc>someone-else@domain.com</cc>
    <cc>again-someone-else@domain.com</cc>
</message>
message-2.xml validates

它有效!

以下是第三个必须无效的XML示例(message-3.xml):

$ xmllint --schema message.xsd message-3.xml 
<?xml version="1.0"?>
<message xmlns="http://yugiohjcj.1s.fr/message">
    <from>me@domain.com</from>
    <from>someone-else@domain.com</from>
    <to>you@domain.com</to>
    <subject>How are you?</subject>
    <subject>How are you again?</subject>
    <body>Hello. How are you? Thank you. Best regards.</body>
    <body>Hello. How are you again? Thank you. Best regards.</body>
</message>
message-3.xml validates

但它有效! 这就是问题所在。

这是我的XML架构(message.xsd):

$ cat message.xsd 
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://yugiohjcj.1s.fr/message" targetNamespace="http://yugiohjcj.1s.fr/message" elementFormDefault="qualified">
    <xs:element name="message">
        <xs:complexType>
            <xs:sequence>
                <xs:choice minOccurs="0" maxOccurs="unbounded">
                    <xs:element name="from"/>
                    <xs:element name="to"/>
                    <xs:element name="cc"/>
                    <xs:element name="subject"/>
                    <xs:element name="body"/>
                </xs:choice>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

我想我需要在某处将maxOccurs属性设置为值1,或者我需要对<xs:sequence><xs:choice>元素进行不同的组合,但我没有找到了如何达到我的目标。

请知道如何修复此XML Schema?

谢谢。

最好的问候。

修改:好的,我使用Relax NG代替XSD 1.0找到了解决问题的方法。它工作正常,并且与libxml2兼容。

这是我的message.rng文件:

$ cat message.rng 
<element name="message" xmlns="http://relaxng.org/ns/structure/1.0">
    <interleave>
        <zeroOrMore>
            <element name="from">
                <text/>
            </element>
        </zeroOrMore>
        <zeroOrMore>
            <element name="to">
                <text/>
            </element>
        </zeroOrMore>
        <zeroOrMore>
            <element name="cc">
                <text/>
            </element>
        </zeroOrMore>
        <optional>
            <element name="subject">
                <text/>
            </element>
        </optional>
        <optional>
            <element name="body">
                <text/>
            </element>
        </optional>
    </interleave>
</element>

以下是我的3个XML示例(message-1.xmlmessage-2.xmlmessage-3.xml)的结果:

$ xmllint --relaxng message.rng message-1.xml 
<?xml version="1.0"?>
<message>
    <from>me@domain.com</from>
    <to>you@domain.com</to>
    <subject>How are you?</subject>
    <body>Hello. How are you? Thank you. Best regards.</body>
</message>
message-1.xml validates
$ xmllint --relaxng message.rng message-2.xml 
<?xml version="1.0"?>
<message>
    <subject>How are you?</subject>
    <body>Hello. How are you? Thank you. Best regards.</body>
    <from>me@domain.com</from>
    <to>you@domain.com</to>
    <to>and-you@domain.com</to>
    <cc>someone-else@domain.com</cc>
    <cc>again-someone-else@domain.com</cc>
</message>
message-2.xml validates
$ xmllint --relaxng message.rng message-3.xml 
<?xml version="1.0"?>
<message>
    <from>me@domain.com</from>
    <from>someone-else@domain.com</from>
    <to>you@domain.com</to>
    <subject>How are you?</subject>
    <subject>How are you again?</subject>
    <body>Hello. How are you? Thank you. Best regards.</body>
    <body>Hello. How are you again? Thank you. Best regards.</body>
</message>
Relax-NG validity error : Extra element subject in interleave
message-3.xml:7: element subject: Relax-NG validity error : Element message failed to validate content
message-3.xml fails to validate

1 个答案:

答案 0 :(得分:0)

在XSD 1.0中,如果要允许元素以任何顺序出现,那么控制每个元素出现频率的唯一方法是使用xs:all,这会将出现次数限制为零或一。所以你无法实现你的目标。

此限制在XSD 1.1中解除。