具有相同元素的XML模式子元素

时间:2013-12-13 17:26:15

标签: xml xsd schema

我正在尝试为接受图像的服务器编写XML模式。图像应该都有掩码或者没有掩码。

我想生成这样的XML:

<?xml version="1.0" encoding="utf-8"?>
<FIVR>
  <meal>
    <media>
      <image2D filename="filename1">
        <mask filename="filename1" />
      </image2D>
      <image2D filename="filename2">
        <mask filename="filename1" />
      </image2D>
      <image2D filename="filename3">
          <mask filename="filename1" />
      </image2D>
      <image2D filename="filename4">
          <mask filename="filename1" />
      </image2D>
      <image2D filename="filename5">
         <mask filename="filename1" />
      </image2D>
    </media>
  </meal>
</FIVR>

<?xml version="1.0" encoding="utf-8"?>
<FIVR>
  <meal>
    <media>
      <image2D filename="filename1">
      </image2D>
      <image2D filename="filename2">
      </image2D>
      <image2D filename="filename3">
      </image2D>
      <image2D filename="filename4">
      </image2D>
      <image2D filename="filename5">
      </image2D>
    </media>
  </meal>
</FIVR>

但是如果某些image2D元素有一个掩码子元素但其他元素没有,则验证应该失败。例如,以下内容应予以拒绝:

<?xml version="1.0" encoding="utf-8"?>
<FIVR>
  <meal>
    <media>
      <image2D filename="filename1">
      </image2D>
      <image2D filename="filename2">
        <mask filename="filename1" />
      </image2D>
      <image2D filename="filename3">
          <mask filename="filename1" />
      </image2D>
      <image2D filename="filename4">
      </image2D>
      <image2D filename="filename5">
      </image2D>
    </media>
  </meal>
</FIVR>

我可以使用XSD架构表达这个吗?

我现在拥有的架构如下所示:

<xs:element name="FIVR">
<xs:complexType>
  <xs:sequence>
    <xs:element name="meal" minOccurs="1" maxOccurs="1">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="media" minOccurs="1" maxOccurs="1">
            <xs:complexType>
              <xs:choice>
                <xs:element name="image2D" minOccurs="5" maxOccurs="5" >
                  <xs:complexType>
                    <xs:all minOccurs="0">
                      <xs:element name="mask">
                        <xs:complexType>
                          <xs:attribute name="filename" type="xs:string" use="required"/>
                        </xs:complexType>
                      </xs:element>
                    </xs:all>
                    <xs:attribute name="filename" type="xs:string" use="required"/>
                  </xs:complexType>
                </xs:element>
              </xs:choice>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xs:sequence>
</xs:complexType>

2 个答案:

答案 0 :(得分:2)

一个简单的解决方案是将媒体声明为 一系列无掩模图像,或一组带掩码的图像。由于这两种图像具有不同的验证行为,因此如果您为它们指定不同的名称,则最简单。然后内容模型变得像

<xs:choice>
  <xs:element ref="image2D-mask" maxOccurs="unbounded"/>
  <xs:element ref="image2D-nomask" maxOccurs="unbounded"/>
</xs:choice>

困难的根源是希望在两个不同的事物上使用相同的名称。

答案 1 :(得分:1)

如果你正在使用XML Schema 1.1 ,你可以specify co-occurrence constraints通过XPath 2.0使用xs:assert这样(未经测试):

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="my/sample/namespace"
           xmlns="my/sample/namespace"
           elementFormDefault="qualified">
  <xs:element name="FIVR">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="meal" minOccurs="1" maxOccurs="1">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="media" minOccurs="1" maxOccurs="1">
                <xs:complexType>
                  <xs:choice>
                    <xs:element name="image2D" minOccurs="5" maxOccurs="5" >
                      <xs:complexType>
                        <xs:all minOccurs="0">
                          <xs:element name="mask">
                            <xs:complexType>
                              <xs:attribute name="filename" type="xs:string" use="required"/>
                            </xs:complexType>
                          </xs:element>
                        </xs:all>
                        <xs:attribute name="filename" type="xs:string" use="required"/>
                      </xs:complexType>
                    </xs:element>
                  </xs:choice>
                  <xs:assert test="(count(image2D/mask) = 0) or (count(image2D/mask) = count(image2D))"/>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

如果您使用的是XML Schema 1.0 ,则无法在架构中表达此类约束,但您可以使用Schematron或在应用程序级别进行检查。