2010-08-01 28 views
16

Với bố cục XML như thế này, tôi đang cố gắng tạo lược đồ XSD để xác nhận hợp lệ nó.Cách tạo lược đồ cho danh sách các nút XML không theo thứ tự, với các ràng buộc xuất hiện

<RootNode> 
    <ChildA /> 
    <ChildC /> 
    <ChildB /> 
    <ChildB /> 
    <ChildA /> 
</RootNode> 

Những yêu cầu như sau:

  • ChildA, ChildB và ChildC có thể xảy ra trong bất kỳ thứ tự. (<xs:sequence> không phù hợp)
  • ChildA là bắt buộc nhưng có thể xảy ra nhiều lần.
  • ChildB là tùy chọn và có thể xảy ra nhiều lần.
  • ChildC là tùy chọn và có thể xảy ra chỉ một lần.

Kỹ thuật tôi thường sử dụng để tạo ra một danh sách có thứ tự các nút là sử dụng một <xs:choice maxOccurs="unbounded"> với mỗi nút có thể có trong danh sách, tuy nhiên, tôi không thể để tạo ra các hạn chế về ChildA và maxOccurs="1" contraint trên ChildC. (Số lần xuất hiện của sự lựa chọn được ưu tiên hơn so với các lần xuất hiện của các phần tử ở đây).

<xs:element name="RootNode"> 
    <xs:complexType> 
    <xs:choice minOccurs="1" maxOccurs="unbounded"> 
     <xs:element name="ChildA" minOccurs="1"/> 
     <xs:element name="ChildB" /> 
     <xs:element name="ChildC" maxOccurs="1"/> 
    </xs:choice> 
    </xs:complexType> 
</xs:element> 
+0

Tôi không nghĩ rằng các lược đồ XML hiện nay là khả năng làm điều này ngay bây giờ. Bạn đã kiểm tra vào các hệ thống xác thực khác, như RelaxNG (www.relaxng.org) có thể ?? –

+0

Câu hỏi liên quan với, tại thời điểm viết bài này, câu trả lời hay hơn: https://stackoverflow.com/questions/2290360/xsd-how-to-allow-elements-in-any-order-any-number-of-times/12012599 – Flow

Trả lời

10

Cập nhật: Trong XSD 1.1m một số khó khăn về all -groups đã được dỡ bỏ. Xem câu trả lời herehere.

Không đơn giản nhưng dường như có thể thực hiện được. Một phần khó khăn ở đây là các định nghĩa lược đồ phải được xác định. Cách tiếp cận tôi sử dụng là hình dung vấn đề bằng cách vẽ một automata hữu hạn của nó và sau đó viết một biểu thức chính quy tương ứng với automata đó. Nó không phải là ở tất cả các phức tạp như nó có thể âm thanh. Tuy nhiên, việc sử dụng một số hệ thống xác nhận khác sẽ có khả năng cung cấp câu trả lời đơn giản hơn.

Tôi đã thực hiện một số thử nghiệm nhưng bỏ lỡ một số trường hợp đặc biệt thật dễ dàng. Vui lòng nhận xét nếu bạn phát hiện ra lỗi.

... và đây là mã:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" > 

    <!-- Schema for elements ChildA, ChildB and ChildC 
     The requirements are as follows: 
      * ChildA, ChildB and ChildC may occur in any order. 
      * ChildA is mandatory but may occur multiple times. 
      * ChildB is optional and may occur multiple times. 
      * ChildC is optional and may occur once only. 
    --> 

    <xsd:element name="root"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element name="ABC-container" type="ABC" maxOccurs="unbounded"/> 
      </xsd:sequence> 
     </xsd:complexType> 
    </xsd:element> 

    <xsd:complexType name="ABC"> 
     <xsd:sequence> 
      <xsd:element name="ChildB" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/> 
      <xsd:choice> 
       <xsd:sequence maxOccurs="1"> 
        <xsd:element name="ChildC" type="xsd:string"/> 
        <xsd:element name="ChildB" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/> 
        <xsd:element name="ChildA" type="xsd:string"/> 
        <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
         <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/> 
         <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/> 
        </xsd:sequence> 
       </xsd:sequence> 
       <xsd:sequence maxOccurs="1"> 
        <xsd:element name="ChildA" type="xsd:string" minOccurs="1"/> 
        <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
         <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/> 
         <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/> 
        </xsd:sequence> 
        <xsd:sequence minOccurs="0" maxOccurs="1"> 
         <xsd:element name="ChildC" type="xsd:string"/> 
         <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
          <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/> 
          <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/> 
         </xsd:sequence> 
        </xsd:sequence> 
       </xsd:sequence> 
      </xsd:choice> 
     </xsd:sequence> 
    </xsd:complexType> 

</xsd:schema> 
+5

"Bằng cách kết hợp và lồng các nhóm khác nhau được cung cấp bởi Lược đồ XML và bằng cách đặt giá trị' minOccurs và maxOccurs', có thể biểu diễn bất kỳ mô hình nội dung nào có thể đọc được bằng DTD XML 1.0. " Nhưng họ không bao giờ nói nó sẽ đẹp. – Will

+0

Jasso.Điều này rất thông minh. Tôi đang cố sửa đổi nó để cung cấp: không có yếu tố bắt buộc (mất ChildA); và nhiều mặt hàng 0-hoặc-1-occurance (như ChildC). Tôi đang gặp rắc rối thực sự. Tôi đã đăng câu hỏi tại http://stackoverflow.com/questions/14321579/how-to-make-a-schema-for-an-unordered-list-where-some-occur-once-some-many-time . Bạn có vẻ là một chuyên gia về điều này. Nếu bạn có thể có một cái nhìn tôi sẽ đánh giá cao nó. – Dave

+0

@Dave Cảm ơn bạn đã đánh giá cao những nỗ lực của tôi. Tôi đã viết một câu trả lời cho câu hỏi của bạn. Nó đến muộn một chút, bởi vì tôi đã không đăng nhập ở đây trong vài tuần. – jasso

1

Tôi chỉ đọc relax-NG shortcut syntax.

Tôi đoán điều này sẽ được ngưng tụ vào trong cú pháp nhỏ gọn thư giãn-ng của sau:

head = element root { ChildA & ChildC? & ChildB* } 

Đó chắc chắn là khá.

+0

Tôi xin lỗi vì sai ... vì ChildA có ít nhất một nhưng có thể nhiều hơn ... – Texas

+0

'head = root element {ChildA + & ChildC? & ChildB *} 'có lẽ? – Alan

2

này nên làm những gì mà bạn chỉ định:

<xs:element name="RootNode"> 
    <xs:complexType>  
    <xs:all>  
     <xs:element name="ChildA" minOccurs="1"/>  
     <xs:element name="ChildB" />  
     <xs:element name="ChildC" minOccurs="0" maxOccurs="1"/>  
    </xs:all> 
    </xs:complexType> 
</xs:element> 
+0

Cảm ơn bạn đã thử, nhưng điều này không hoàn toàn phù hợp. A và B có thể xuất hiện nhiều lần, nhưng phần tử '' chỉ định rằng mỗi phần tử trong phần tử đó có thể xuất hiện bằng 0 hoặc chỉ một lần. Sẽ tốt hơn nếu có một giải pháp đơn giản như thế này, nhưng tôi nghĩ giải pháp của jasso có lẽ là giải pháp tốt nhất mà chúng tôi có được. –

+1

điều gì sẽ xảy ra nếu bạn đặt minOccurs = 1 và maxOccurs = 1 cho tất cả các phần tử con? –

+0

Câu trả lời đó là chính xác (AFAIKT) nếu bạn sử dụng [XSD 1.1] (https://www.w3.org/TR/xmlschema11-1/). [G1.3 5.] (https://www.w3.org/TR/xmlschema11-1/#changes) giải thích sự khác biệt giữa XSD 1.0 cho phép điều này. – Flow

Các vấn đề liên quan