如何验证子元素是否存在而不指定XML Schema中的顺序?

时间:2014-01-30 15:57:21

标签: xml xsd xsd-1.0

我正在尝试开发XML Schema文件来验证Person元素。我们的申请要求某人拥有FirstNameLastName但不关心他们的订单。它还允许将其他元素放在Person元素下。所以以下内容是有效的:

<person>
    <firstName>Jon</firstName>
    <lastName>Smith</lastName>
</person>

<person>
    <lastName>Smith</lastName>
    <firstName>Jon</firstName>
</person>

<person>
    <title>Mr</title>
    <firstName>Jon</firstName>
    <lastName>Smith</lastName>
</person>

<person>
    <title>Mr</title>
    <lastName>Smith</lastName>
    <firstName>Jon</firstName>
    <suffix>CEng</suffix>
</person>

<person>
    <title>Mr</title>
    <lastName>Smith</lastName>
    <middleInitial>G</middleInitial>
    <firstName>Jon</firstName>
    <suffix>CEng</suffix>
</person>

但是,以下内容无效,因为它没有firstName

<person>
    <title>Mr</title>
    <lastName>Smith</lastName>
    <suffix>CEng</suffix>
</person>

我尝试创建这样的复杂类型:

<xsd:element name="person">
    <xsd:complexType>
        <xsd:all>
            <xsd:element minOccurs="1" maxOccurs="1" name="firstName" />
            <xsd:element minOccurs="1" maxOccurs="1" name="lastName"/>
            <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" />
        </xsd:all>
    </xsd:complexType>
</xsd:element>

但显然any内不允许all。是否有可能让XML Schema进行此验证?如果是这样的话?

1 个答案:

答案 0 :(得分:1)

如果您有XML Schema 1.1验证器:

<xsd:element name="person">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" />
        </xsd:sequence>
    </xsd:complexType>
    <xsd:assert test="firstName and lastName"/>
</xsd:element>

在xsd 1.1中,在xsd:all中有xsd:any是有效的但是如果未指定的元素与firstName和lastName在同一名称空间中,它仍然可能导致错误,因为内容模型不明确。但是xsd:assert会起作用。

在xsd 1.0中,您可以指定元素可以作为带有选项的序列的所有订单。但是,除firstName和lastName之外的元素需要位于不同的命名空间中,否则会在架构上出现此“模糊内容模型”错误。我不确定你是否可以在数据中使用这个“其他命名空间”约束,但我认为这是在Xml Schema 1.0版中对此进行建模的唯一方法。

<强> XSD

<?xml version="1.0" encoding="utf-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:element name="persons">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="person" minOccurs="1" maxOccurs="unbounded" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="firstName" />
    <xsd:element name="lastName" />
    <xsd:element name="person">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
                <xsd:choice>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" ref="firstName" />
                        <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
                        <xsd:element minOccurs="1" maxOccurs="1" ref="lastName" />
                    </xsd:sequence>
                    <xsd:sequence>
                        <xsd:element minOccurs="1" maxOccurs="1" ref="lastName" />
                        <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
                        <xsd:element minOccurs="1" maxOccurs="1" ref="firstName" />
                    </xsd:sequence>
                </xsd:choice>
                <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="skip" namespace="##other" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

输入XML

<?xml version="1.0"?>
<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd" xmlns:o="urn:foobar">
    <person>
        <firstName>Jon</firstName>
        <lastName>Smith</lastName>
    </person>

    <person>
        <lastName>Smith</lastName>
        <firstName>Jon</firstName>
    </person>

    <person>
        <o:title>Mr</o:title>
        <firstName>Jon</firstName>
        <lastName>Smith</lastName>
    </person>

    <person>
        <o:title>Mr</o:title>
        <lastName>Smith</lastName>
        <firstName>Jon</firstName>
        <o:suffix>CEng</o:suffix>
    </person>

    <person>
        <o:title>Mr</o:title>
        <lastName>Smith</lastName>
        <o:middleInitial>G</o:middleInitial>
        <firstName>Jon</firstName>
        <o:suffix>CEng</o:suffix>
    </person>
</persons>