使用 XSD 1.1 限制基于另一个属性的元素 [英] restriction of elements based on another attribute using XSD 1.1

查看:27
本文介绍了使用 XSD 1.1 限制基于另一个属性的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 XSD 1.1 创建架构定义,其中其他元素的数量取决于另一个元素的属性.例如.BaPath 元素的数量 BaPath 取决于Conn"元素的属性service"的值.我写的xsd是

I am trying to create a schema definition using XSD 1.1 in which the number of other elements is dependent on the attribute of another element. E.g. The number of the BaPath elements BaPath depends on the value of the attribute "service" of the "Conn" element. The xsd I wrote is

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:element name="Mapping">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="Link" minOccurs="0" maxOccurs="unbounded" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="Env">
        <xsd:complexType>
            <xsd:attribute name="name" use="required">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:string">
                        <xsd:enumeration value="UTEST" />
                        <xsd:enumeration value="TEST" />
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="Link">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="Conn" maxOccurs="unbounded" />
            </xsd:sequence>
            <xsd:attribute name="service" use="required">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:string">
                        <xsd:enumeration value="FILESNF" />
                        <xsd:enumeration value="MSGSNF" />
                        <xsd:enumeration value="MSGRT" />
                        <xsd:enumeration value="FILERT" />
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="Conn">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="BaPath" maxOccurs="unbounded" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="BaPath">
        <xsd:complexType>
            <xsd:attribute name="flow" use="required">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:string">
                        <xsd:assertion test="@service eq 'MSGRT'">
                            <xsd:enumeration value="TRS" />
                            <xsd:enumeration value="ZTRS" />
                        </xsd:assertion>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="Dep">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="Env" maxOccurs="unbounded" />
                <xsd:element ref="Mapping" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <xsd:complexType name="CfgType">
        <xsd:sequence>
            <xsd:element ref="Dep" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="Cfg" type="CfgType"></xsd:element>

</xsd:schema>
</Cfg>

例如,如果 Conn 元素具有属性 service eq 'MSGRT',则必须有 2 个 BaPath 元素具有 TRS 和 ZTRS 属性

for example if Conn element has an attribute service eq 'MSGRT' there must be 2 BaPath elements with attributes TRS and ZTRS

<Cfg xmlns="http://www.alpha.com/beta">
  <Dep>
    <Env name="UTEST"/>
    <Mapping>
      <Link t2s_service="MSGRT">
        <Conn>
          <BaPath flow="ZTRS"/>
          <BaPath flow="TRS"/>
        </Conn>
      </Link>
    </Mapping>
  </Dep>

如果服务 eq 'FILESNF' of Conn 必须有 3 个 BaPath 元素,其属性为 FTS、ZFTS 和 MSSDN

if service eq 'FILESNF' of Conn there must 3 BaPath elements with attributes FTS, ZFTS and MSSDN

我尝试了不同的解决方案,但似乎没有一个可行.用xsd-1.1的断言可以解决这个问题吗?

I tried different solutions but no one seems to work. Is it possbile to solve this problem with assertion of xsd-1.1?

推荐答案

您可以在 Link 元素中使用 asserts(和枚举flow 属性中的所有值).

You could use asserts in the Link element (and a enumeration with all the values in the flow attribute).

<xsd:element name="Link">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element ref="Conn" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="service" use="required">
            <xsd:simpleType>
                <xsd:restriction base="xsd:string">
                    <xsd:enumeration value="FILESNF"/>
                    <xsd:enumeration value="MSGSNF"/>
                    <xsd:enumeration value="MSGRT"/>
                    <xsd:enumeration value="FILERT"/>
                </xsd:restriction>
            </xsd:simpleType>
        </xsd:attribute>
        <xsd:assert test="(@service ne 'MSGRT') or (count(Conn[count(BaPath[@flow eq 'TRS']) eq 1 and count(BaPath[@flow eq 'ZTRS']) eq 1 and count(BaPath) eq 2]) eq count(Conn))"></xsd:assert>
        <xsd:assert test="(@service ne 'FILESNF') or (count(Conn[count(BaPath[@flow eq 'FTS']) eq 1 and count(BaPath[@flow eq 'MSSDN']) eq 1 and count(BaPath[@flow eq 'ZFTS']) eq 1 and count(BaPath) eq 3]) eq count(Conn))"></xsd:assert>
    </xsd:complexType>
</xsd:element>

对其中一个断言的解释(其他断言类似):

Explanation of one of the assert (the other asserts would be similar):

(@service ne 'MSGRT') or (count(Conn[count(BaPath[@flow eq 'TRS']) eq 1 and count(BaPath[@flow eq 'ZTRS']) eq 1 andcount(BaPath) eq 2]) eq count(Conn))

首先我们检查 service 属性.然后,使用 Conn[count(BaPath[@flow eq 'TRS']) eq 1 and count(BaPath[@flow eq 'ZTRS']) eq 1 and count(BaPath) eq 2]正在选择 Link 的所有 Conn 元素,这些元素恰好有两个 BaPath 子元素(一个带有 flow=TRS,另一个带有 flow=ZTRS).之后,我们检查所有 Conn 元素是否都通过了该限制.

First we check the service attribute. Then, using Conn[count(BaPath[@flow eq 'TRS']) eq 1 and count(BaPath[@flow eq 'ZTRS']) eq 1 and count(BaPath) eq 2] we are selecting all the Conn element of the Link that have exactly two BaPath childs (one with flow=TRS and other with flow=ZTRS). After that we check that all of the Conn elements pass that restriction.

所以,使用它,这个例子将是有效的:

So, using that, this example will be valid:

<Link service="MSGRT">
    <Conn>
        <BaPath flow="TRS"></BaPath>
        <BaPath flow="ZTRS"></BaPath>
    </Conn>    
</Link>

此示例无效:

<Link service="MSGRT">
    <Conn>
        <BaPath flow="MSSDN"></BaPath>
        <BaPath flow="ZTRS"></BaPath>
    </Conn>    
</Link>

此示例无效:

<Link service="MSGRT">
    <Conn>
        <BaPath flow="TRS"></BaPath>
    </Conn>    
</Link>

此示例无效:

<Link service="MSGRT">
    <Conn>
        <BaPath flow="TRS"></BaPath>
        <BaPath flow="ZTRS"></BaPath>
        <BaPath flow="ZFTS"></BaPath>
    </Conn>    
</Link>

另一种选择是使用条件类型替代(例如此处),但您可能需要复制部分架构.

Another option it's to use conditional type alternatives (example here), but you would probably need to duplicate parts of your Schema.

这篇关于使用 XSD 1.1 限制基于另一个属性的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆