如何使<xsd:key>仅适用于当前范围?</xsd:key>

时间:2013-03-22 12:48:23

标签: xml xpath xsd

好的,基本上我现在拥有的是:

XSD:

<?xml version="1.0"?>
<xsd:schema xmlns="test"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="test"
            elementFormDefault="qualified">

    <xsd:complexType name="fields">
        <xsd:choice minOccurs="1" maxOccurs="unbounded">
            <xsd:element name="text">
                <xsd:complexType>
                    <xsd:attribute name="id" type="xsd:string" use="required"/>
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="group">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="fields" type="fields"/>
                    </xsd:sequence>
                    <xsd:attribute name="id" type="xsd:string" use="required"/>
                </xsd:complexType>
            </xsd:element>
        </xsd:choice>
    </xsd:complexType>

    <xsd:element name="root">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="fields" type="fields" minOccurs="0" maxOccurs="unbounded">
                    <xsd:key name="fieldId">
                        <xsd:selector xpath=".//*"/>
                        <xsd:field xpath="@id"/>
                    </xsd:key>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

XML:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="test">

    <fields>
        <text id="asd"/>
        <text id="sdf"/>
        <group id="dfg">
            <fields>
                <text id="asd"/>
                <text id="sdf"/>
            </fields>
        </group>
    </fields>

</root>

显然,根据XSD,XML无效,因为ID有重复,但问题是,我希望id只能在自己的范围内进行验证,换句话说,这个应该失败:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="test">

    <fields>
        <text id="asd"/>
        <text id="asd"/>
    </fields>

</root>

虽然这应该通过:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="test">

    <fields>
        <text id="asd"/>
        <group id="sdf">
            <fields>
                <text id="asd"/>
            </fields>
        </group>
    </fields>

</root>

为了说清楚,我计划在解析XML时将父ID添加到子ID中,因此我不关心嵌套ID是否重复,而不是同样的范围,因为我希望能够达到类似的结果:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="test">

    <fields>
        <group id="eventA_time">
            <fields>
                <text id="hour"/>
                <text id="minute"/>
                <text id="second"/>
            </fields>
        </group>
        <group id="eventB_time">
            <fields>
                <text id="hour"/>
                <text id="minute"/>
                <text id="second"/>
            </fields>
        </group>
    </fields>

</root>

3 个答案:

答案 0 :(得分:0)

能够搜索亲戚:

更改:

<xsd:key name="fieldId">
    <xsd:selector xpath=".//*"/>
    <xsd:field xpath="@id"/>
</xsd:key>

<xsd:key name="fieldId">
    <xsd:selector xpath="*"/>
    <xsd:field xpath="@id"/>
</xsd:key>

答案 1 :(得分:0)

只需将选择器从.//*更改为*(或text)。

答案 2 :(得分:0)

由于我没有得到完全符合我需要的答案,我只会发布一个版本的XSD,它可以正常工作,但由于某些部分被复制,仍然看起来很丑陋:

<?xml version="1.0"?>
<xsd:schema xmlns="test"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="test"
            elementFormDefault="qualified">

    <xsd:complexType name="fields">
        <xsd:choice minOccurs="1" maxOccurs="unbounded">
            <xsd:element name="text">
                <xsd:complexType>
                    <xsd:attribute name="id" type="xsd:string" use="required"/>
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="group">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="fields" type="fields" minOccurs="0" maxOccurs="unbounded">
                            <xsd:key name="innerFieldId">
                                <xsd:selector xpath="*"/>
                                <xsd:field xpath="@id"/>
                            </xsd:key>
                        </xsd:element>
                    </xsd:sequence>
                    <xsd:attribute name="id" type="xsd:string" use="required"/>
                </xsd:complexType>
            </xsd:element>
        </xsd:choice>
    </xsd:complexType>

    <xsd:element name="root">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="fields" type="fields" minOccurs="0" maxOccurs="unbounded">
                    <xsd:key name="fieldId">
                        <xsd:selector xpath="*"/>
                        <xsd:field xpath="@id"/>
                    </xsd:key>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>