【问题标题】:XPath assertion in an xsd schemaxsd 模式中的 XPath 断言
【发布时间】:2022-06-13 22:09:08
【问题描述】:

我有以下 xsd 架构

 <?xml version="1.1" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace = "http://www.ludd21.com/kPartModel"
xmlns = "http://www.ludd21.com/kPartModel"
elementFormDefault="qualified"
>   
    <xs:element name="kPartModel">
      <xs:complexType>
        <xs:sequence>
          <xs:element ref="kPartsPiece"  minOccurs="1" maxOccurs = "unbounded"/>
        </xs:sequence>
        <xs:attribute name="modelName" type="xs:NCName" use = "required"/>
      </xs:complexType>
       <!--piecename must be unique within kpModel-->
      <xs:unique name= "kPartModel">
            <xs:selector xpath="*"/>
            <xs:field xpath= "@pieceName"/>
          </xs:unique>
    </xs:element>
    
    <xs:element name="kPartsPiece">
        <xs:complexType>
          <xs:sequence>
            <xs:element ref= "kPartsList"/>
          </xs:sequence>         
          <xs:attribute name="pieceName" type="xs:NCName"/>
         <!-- if they exist previousnum and nextsnum must contain valid partNumber that is referring to a part in kpartsList-->
         <xs:assert test = "every $x in kPartsList/@previousnums satisfies exists(kPartsList/@partNumber)"/>
         <xs:assert test = "every $x in kPartsList/@nextsnums satisfies exists (kPartsList/@partNumber)"/>
        </xs:complexType>
        <!-- @partNumber is unique across kPartsList -->
        <xs:unique name= "kPartsList">
          <xs:selector xpath="*"/>
          <xs:field xpath= "@partNumber"/>
        </xs:unique>
    </xs:element>
  
    <xs:element name = "kPartsList" >
      <xs:complexType>
        <xs:sequence>
          <xs:choice >
            <xs:element ref = "castOnPartSeg"/>
            <xs:element ref = "castOnPartPoint"/>
          </xs:choice>
          <xs:choice  minOccurs= "0" maxOccurs = "unbounded">
            <xs:element ref = "castOnPartSeg" />
            <xs:element ref = "castOnPartPoint" />
            <xs:element ref = "castOffPartSeg" />
            <xs:element ref = "castOffPartPoint"/>
            <xs:element ref = "joinPart"/>
            <xs:element ref = "splitPart" />
            <xs:element ref = "segSplitPart"/>  
          </xs:choice>
        </xs:sequence>        
      </xs:complexType>      
      </xs:element>
    
    
    <xs:element name="castOnPartPoint">
      <xs:complexType>
         <xs:attribute name ="nextsnum" type = "kpRefsList" use = "required"/>
         <xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
         <xs:attribute name = "heightd" type = "decimal5digits" use = "required"/>
      </xs:complexType>
    </xs:element>
      
    <xs:element name="castOnPartSeg">
      <xs:complexType>
        <xs:attribute name = "nextsnum"  type = "kpRefsList" use = "required"/>
        <xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
        <xs:attribute name = "heightd" type = "decimal5digits" use = "required"/>
      </xs:complexType>
    </xs:element>

    
    <xs:element name="castOffPartPoint">
      <xs:complexType>
         <xs:attribute name ="previousnum" type = "kpRefsList" use = "required"/> 
        <xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
        <xs:attribute name = "heightd" type = "decimal5digits" fixed = "0" use = "required"/>
      </xs:complexType>
    </xs:element>
    
    
    <xs:element name="castOffPartSeg">
     <xs:complexType>
        <xs:attribute name ="previousnum" type = "kpRefsList" use = "required"/> 
        <xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
        <xs:attribute name = "heightd" type = "decimal5digits" fixed="0" use = "required"/>
      </xs:complexType> 
    </xs:element>

    
    <xs:element name="splitPart">
      <xs:complexType>
        <xs:attribute name ="previousnum" type = "kpRefsList" use = "required"/> 
        <xs:attribute name ="nextsnum" type = "kpRefsList" use = "required"/>
        <xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
        <xs:attribute name = "heightd" type = "decimal5digits" use = "required"/>
      </xs:complexType>
    </xs:element>
    
    <xs:element name="segSplitPart">
      <xs:complexType>
        <xs:attribute name ="previousnum"  type = "kpRefsList" use = "required"/>        
        <xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
        <xs:attribute name = "heightd" type = "decimal5digits" fixed= "0" use = "required"/>       
      </xs:complexType>
    </xs:element>
    
    <xs:element name="joinPart">
      <xs:complexType>
        <xs:attribute name ="nextsnum"  type = "kpRefsList" use = "required"/>   
        <xs:attribute name ="previousnum" type = "kpRefsListmin2" use = "required"/>
         <xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
         <xs:attribute name = "heightd" type = "decimal5digits" use = "required"/>      
      </xs:complexType>
    </xs:element>

    <xs:simpleType name = "kpRefsList">
        <xs:list itemType= "xs:nonNegativeInteger"/>
    </xs:simpleType>
    
    <xs:simpleType name="kpRefsListmin2"> 
        <xs:restriction base = "kpRefsList"> 
        <xs:minLength value = "2"/>
      </xs:restriction>
    </xs:simpleType>
  
   
    <xs:simpleType name ="decimal5digits">
        <xs:restriction base = "xs:decimal">
            <xs:fractionDigits value="5"/>
        </xs:restriction>
    </xs:simpleType>    
</xs:schema>

它在第 28 行和第 29 行包含不正确的断言。我尝试了几种解决方案,但作为 XPath 中的一个完整新手,我没有成功。目标是测试 previousnum 中的每个数字(与 nextsnum 相同)对于 kPartsPiece 的 kPartsList 中的零件是有效的零件号。

下面是一个 xml 片段,应该根据架构进行验证;

<ns0:kPartModel xmlns:ns0="http://www.ludd21.com/kPartModel" modelName="manysingulars">
<ns0:kPartsPiece pieceName="manysingulars">
    <ns0:kPartsList>
        <ns0:castOnPartSeg nextsnum="1" partNumber="0" heightd="11.82912" />
        <ns0:joinPart nextsnum="3" previousnum="0 2" partNumber="1" heightd="8.08932" />
        <ns0:castOnPartPoint nextsnum="1" partNumber="2" heightd="3.80881" />
        <ns0:joinPart nextsnum="6" previousnum="1 5 4" partNumber="3" heightd="8.65979" />
        <ns0:castOnPartSeg nextsnum="3" partNumber="4" heightd="16.36741" />
        <ns0:castOnPartSeg nextsnum="3" partNumber="5" heightd="6.48911" />
        <ns0:joinPart nextsnum="8 9 10" previousnum="3 7" partNumber="6" heightd="5.23755" />
        <ns0:castOnPartPoint nextsnum="6" partNumber="7" heightd="18.12524" />
        <ns0:splitPart previousnum="6" nextsnum="12" partNumber="8" heightd="8.63775" />
        <ns0:splitPart previousnum="6" nextsnum="11" partNumber="9" heightd="8.63775" />
        <ns0:segSplitPart previousnum="6" partNumber="10" heightd="0.00000" />
        <ns0:castOffPartSeg previousnum="9" partNumber="11" heightd="0.00000" />
        <ns0:castOffPartSeg previousnum="8" partNumber="12" heightd="0.00000" />
    </ns0:kPartsList>
</ns0:kPartsPiece>

【问题讨论】:

  • partNumber 设为xs:ID 和其他两个属性xs:IDREFS 可能更容易。

标签: xsd assertion xpath-2.0


【解决方案1】:

这是一个稍微简化但与您的需求相似的示例,具有列表类型和断言:

<?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="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="parts"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="parts">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" ref="part"/>
            </xs:sequence>
            <xs:assert id="test-reference-id" test="every $part in part satisfies every $id in $part/data(@next) satisfies some $part2 in part satisfies $id = $part2/@id"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="part">
        <xs:complexType>
            <xs:attribute name="id" use="required" type="xs:string"/>
            <xs:attribute name="next" type="id-list"/>
        </xs:complexType>
    </xs:element>
    <xs:simpleType name="id-list">
        <xs:list itemType="xs:string"></xs:list>
    </xs:simpleType>
</xs:schema>

例子

<root>
    <parts>
        <part id="p1" next="p2 p4"/>
        <part id="p2" next="p3 p4 p5"/>
        <part id="p3" next="p4"/>
        <part id="p4"/>
    </parts>
</root>

然后断言失败而

<root>
    <parts>
        <part id="p1" next="p2 p4"/>
        <part id="p2" next="p3 p4"/>
        <part id="p3" next="p4"/>
        <part id="p4"/>
    </parts>
</root>

有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多