XML XSD1.1 断言中使用 XPath 查询的元素限制

XML element restriction using XPath query in XSD1.1 assert

我写了 "music.xsd" 来验证下面的 "music.xml" 文件。在音乐文件中有两个专业化 styleSpec 和 ensembleSpec。

 <specialization name="styleSpec">
    <entity name="Symphonic">
    </entity>    
 </specialization>

 <specialization name="ensembleSpec">
    <entity name="Orchestra">
    </entity>   
 </specialization>

"styleSpec" 允许的实体是 Symphonic、Folk 和 Jazz。

"ensembleSpec" 允许的实体是 Orchestra、SmallGroup 和 Soloist。

我想添加以下限制:

  1. 如果 styleSpec 中的实体是 Symphonic,那么 ensembleSpec 中的实体必须是 Orchestra。

  2. 如果 styleSpec 中的实体是 Folk,则 ensembleSpec 中的实体必须是 SmallGroup 或 Soloist。

  3. 如果 styleSpec 中的实体是 Jazz,那么 ensembleSpec 中的实体必须是 Orchestra 或 SmallGroup。

我可以在另一个 XSD 文件中执行此操作(another.xsd,如下所示)但是当我在 music.xsd 中添加该断言语句时它不起作用。

我该如何解决这个问题?

music.xml

<?xml version="1.0" encoding="UTF-8"?>
<entity xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="music.xsd" 
 name="MusicPerformances"> 

<multiAspect name="musicPerformancesMAsp">
 <entity name="MusicPerformance">

 <specialization name="styleSpec">
  <entity name="Symphonic">
  </entity>    
 </specialization>

 <specialization name="ensembleSpec">
  <entity name="Orchestra">
  </entity>   
 </specialization>

 </entity>
</multiAspect> 

</entity>    

music.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
elementFormDefault="qualified"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1">

<xs:complexType name="aspectType">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="entity"/>
    </xs:sequence>
    <xs:attribute name="name" use="required"/>
</xs:complexType>

<xs:complexType name="multiAspectType">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="entity"/>
    </xs:sequence>
    <xs:attribute name="name" use="required"/>
</xs:complexType>

<xs:complexType name="specializationType">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="entity"/>
    </xs:sequence>
    <xs:attribute name="name" use="required"/>
</xs:complexType>


<xs:complexType name="varType"> 
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="entity"/>
    </xs:sequence>
    <xs:attribute name="name" use="required"/>

</xs:complexType>


<xs:element name="entity">
    <xs:complexType>
        <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element ref="aspect"/>
                <xs:element ref="specialization"/>
                <xs:element ref="multiAspect"/>
                <xs:element ref="var"/>

            </xs:choice>            

        </xs:sequence>

        <xs:attribute name="name" use="required"/>

        <xs:assert test="every $x in .//entity satisfies empty($x//*[@name = $x/@name])"/>
        <!--   

        <xs:assert test=
            **// Maybe have to add XPath query here. But I am not sure where 
              i will add.**
        />

          --> 
    </xs:complexType> 

    <xs:unique name="entityunqall">
        <xs:selector xpath="*/entity"/>            
        <xs:field xpath="@name"/>
    </xs:unique> 


</xs:element>

<xs:element name="aspect" type="aspectType"/>
<xs:element name="multiAspect" type="multiAspectType"/>
<xs:element name="specialization" type="specializationType"/>
<xs:element name="var" type="varType"/>   

another.xml 文件与 another.xsd 一起正常工作。

another.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
elementFormDefault="qualified" 
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1"> 

<xs:element name="styleSpec">       
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:enumeration value="Symphonic" />
            <xs:enumeration value="Folk" />
            <xs:enumeration value="Jazz" />
        </xs:restriction>
    </xs:simpleType>
</xs:element> 

<xs:element name="ensembleSpec">       
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:enumeration value="Orchestra" />
            <xs:enumeration value="SmallGroup" />
            <xs:enumeration value="Soloist" />
        </xs:restriction>
    </xs:simpleType>
</xs:element>

<xs:element name="MusicalPerformance">
    <xs:complexType>
        <xs:sequence>                 
            <xs:element ref="styleSpec"/>
            <xs:element ref="ensembleSpec"/>                      
        </xs:sequence>
        <xs:assert test="(styleSpec = 'Symphonic' and ensembleSpec=('Orchestra'))
            or
            (styleSpec = 'Folk' and ensembleSpec=('SmallGroup','Soloist'))
            or
            (styleSpec = 'Jazz' and ensembleSpec=('Orchestra','SmallGroup'))
            "/>
    </xs:complexType>
</xs:element>



</xs:schema>

another.xml

<?xml version="1.0" encoding="UTF-8"?>
<MusicalPerformance xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="another.xsd">
    <styleSpec>Folk</styleSpec>
    <ensembleSpec>Soloist</ensembleSpec>     
</MusicalPerformance>

编辑

我已经更改了音乐文件,新文件如下:

music.xml

<?xml version="1.0" encoding="UTF-8"?>
<entity xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="musicalperformances.xsd" 
name="MusicPerformances">

  <multiAspect name="MusicPerformancesMAsp">
  <entity name="MusicPerformance">
  <aspect name="MusicPerformanceDec">
    <entity name="Music">
      <specialization name="styleSpec">
        <entity name="Jazz">
        </entity>
      </specialization>
    </entity>
    <entity name="Performer">
      <specialization name="ensembleSpec">
        <entity name="SmallGroup">
        </entity>
      </specialization>
    </entity>
  </aspect>
  </entity>
  </multiAspect>


  </entity>

首先,断言需要在两个特化元素的父元素上进行(即在 multiAspect 元素的级别)。您没有在您的问题或评论中明确说明您提出断言的位置,这可能表明您没有意识到正确执行此操作的重要性。

那么规则就很简单了,例如:

if the entity inside styleSpec is Symphonic then the entity inside ensembleSpec must be Orchestra.

test="if (specialization[@name='styleSpec']/entity/@name='Symphonic')
      then specialization(@name='ensembleSpec']/entity/@name='Orchestra' 
      else true()"