首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用XSD 1.1限制基于另一个属性的元素

使用XSD 1.1限制基于另一个属性的元素
EN

Stack Overflow用户
提问于 2014-08-01 14:29:15
回答 1查看 7.4K关注 0票数 2

我试图使用XSD1.1创建一个模式定义,其中其他元素的数量取决于另一个元素的属性。例如,BaPath元素BaPath的数量取决于"Conn“元素的属性"service”的值。我写的xsd是

代码语言:javascript
复制
<?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元素具有属性服务eq 'MSGRT‘,则必须有两个具有属性TRS和ZTRS的BaPath元素。

代码语言:javascript
复制
<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>

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

我尝试过不同的解决方案,但似乎没有人能奏效。是否使用xsd-1.1断言来解决这个问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-01 22:00:34

您可以使用 Link 元素中使用断言(以及包含flow属性中所有值的枚举)。

代码语言:javascript
复制
<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>

对其中一项主张的解释(另一项主张类似):

(@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))

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

因此,使用这个示例将是有效的:

代码语言:javascript
复制
<Link service="MSGRT">
    <Conn>
        <BaPath flow="TRS"></BaPath>
        <BaPath flow="ZTRS"></BaPath>
    </Conn>    
</Link>

此示例将无效:

代码语言:javascript
复制
<Link service="MSGRT">
    <Conn>
        <BaPath flow="MSSDN"></BaPath>
        <BaPath flow="ZTRS"></BaPath>
    </Conn>    
</Link>

此示例将无效:

代码语言:javascript
复制
<Link service="MSGRT">
    <Conn>
        <BaPath flow="TRS"></BaPath>
    </Conn>    
</Link>

此示例将无效:

代码语言:javascript
复制
<Link service="MSGRT">
    <Conn>
        <BaPath flow="TRS"></BaPath>
        <BaPath flow="ZTRS"></BaPath>
        <BaPath flow="ZFTS"></BaPath>
    </Conn>    
</Link>

编辑:

另一个选项是使用conditional type alternatives (例如这里),但是您可能需要复制模式的部分。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25082505

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档