2012-01-25 41 views
17

tôi có một lựa chọn complexType tên abType:Làm thế nào để mở rộng một complexType lựa chọn mà không cần giải trình tự lựa chọn?

<xs:complexType name="abType"> 
    <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:element name="a"/> 
     <xs:element name="b"/> 
    </xs:choice> 
</xs:complexType> 

loại này có thể được sử dụng để tạo ra các yếu tố với ab nút trong bất kỳ thứ tự như thế này ví dụ:

<ab> 
    <b/> 
    <a/> 
</ab> 

Bây giờ tôi muốn tạo một loại có nguồn gốc được gọi là abcType để cho phép các nút a, bc theo bất kỳ thứ tự nào. Vì vậy, tôi đã tạo ra một complexType mới dựa trên abType:

<xs:complexType name="abcType"> 
    <xs:complexContent> 
     <xs:extension base="abType"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element name="c"/> 
      </xs:choice> 
     </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 

Sau đó tôi tạo ra một nút abc:

<abc> 
    <c/> 
    <b/> 
    <a/> 
</abc> 

Nhưng nút này là không hợp lệ ! Không được đặt bất kỳ số a hoặc b nào sau c. Lý do là, mà phát sinh một loại từ một loại cơ sở tạo ra một chuỗi implicite mặc dù cả hai loại là sự lựa chọn. XMLSpy minh họa nó theo cách này:

Extended Choice Type

Kết quả này là khá vô dụng với nhiều loại lựa chọn.

Vì vậy, câu hỏi của tôi là: Làm cách nào để mở rộng loại lựa chọn mà không cần giải trình tự lựa chọn?

Đây là XSD đầy đủ và kiểm tra tệp tin XML để tạo lại vấn đề:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> 
<xs:element name="root"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="ab"/> 
      <xs:element ref="abc"/> 
     </xs:sequence> 
    </xs:complexType> 
</xs:element> 
<xs:element name="ab" type="abType"/> 
<xs:complexType name="abType"> 
    <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:element name="a"/> 
     <xs:element name="b"/> 
    </xs:choice> 
</xs:complexType> 
<xs:element name="abc" type="abcType"/> 
<xs:complexType name="abcType"> 
    <xs:complexContent> 
     <xs:extension base="abType"> 
      <xs:choice minOccurs="0" maxOccurs="unbounded"> 
       <xs:element name="c"/> 
      </xs:choice> 
     </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 
</xs:schema> 

Ví dụ:

<?xml version="1.0" encoding="UTF-8"?> 
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="inherit-choice.xsd"> 
<ab> 
    <b/> 
    <a/> 
</ab> 
<abc> 
    <c/> 
    <b/> 
    <a/> 
</abc> 
</root> 

Trả lời

10

Thật không may, câu trả lời ngắn gọn là NO, bạn không thể mở rộng một lựa chọn compositor. Về mặt logic, nếu có một số loại quan hệ giữa a, b và c (như trong Java, .NET, mọi thứ cuối cùng là một đối tượng, bạn có thể làm tương tự trong XSD) thì tôi đề nghị sử dụng các nhóm thay thế thay thế (hoặc, nếu bạn thích, một cái gì đó dựa trên xsi: type).

CẬP NHẬT với ví dụ. XSD-1:

<?xml version="1.0" encoding="utf-8" ?> 
<!--W3C Schema generated by QTAssistant/W3C Schema Refactoring Module (http://www.paschidev.com)--> 
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

    <xsd:element name="ab" type="abType"/> 

    <xsd:complexType name="abType"> 
     <xsd:sequence> 
      <xsd:element ref="ExtensibleChoice-A" minOccurs="0" maxOccurs="unbounded"/> 
     </xsd:sequence> 
    </xsd:complexType> 

    <xsd:element name="ExtensibleChoice-A" type="ExtensibleChoiceBaseType" abstract="true" /> 

    <xsd:complexType name="ExtensibleChoiceBaseType" abstract="true"> 
     <xsd:sequence/> 
    </xsd:complexType> 

    <xsd:element name="a" substitutionGroup="ExtensibleChoice-A" type="aType" block="#all"/> 
    <xsd:element name="b" substitutionGroup="ExtensibleChoice-A" type="bType" block="#all"/> 
    <xsd:element name="c" substitutionGroup="ExtensibleChoice-A" type="cType" block="#all"/> 

    <xsd:complexType name="aType"> 
     <xsd:complexContent> 
      <xsd:extension base="ExtensibleChoiceBaseType"> 
       <xsd:sequence> 
        <xsd:element name="aChild" type="xsd:string"/> 
       </xsd:sequence> 
      </xsd:extension> 
     </xsd:complexContent> 
    </xsd:complexType> 
    <xsd:complexType name="bType"> 
     <xsd:complexContent> 
      <xsd:extension base="ExtensibleChoiceBaseType"> 
       <xsd:sequence> 
        <xsd:element name="bChild" type="xsd:int"/> 
       </xsd:sequence> 
      </xsd:extension> 
     </xsd:complexContent> 
    </xsd:complexType> 
    <xsd:complexType name="cType"> 
     <xsd:complexContent> 
      <xsd:extension base="ExtensibleChoiceBaseType"> 
       <xsd:sequence> 
        <xsd:element name="cChild" type="xsd:string"/> 
       </xsd:sequence> 
      </xsd:extension> 
     </xsd:complexContent> 
    </xsd:complexType> 
</xsd:schema> 

Members of the substitution group

các khả năng mở rộng là tại một thời điểm nào, bạn có thể chỉ có một , bc như các thành viên. Nếu bạn hoặc một người tiêu dùng, quyết định thêm một cái gì đó (nói một d phần tử), sau đó bạn chỉ cần tạo một sơ đồ chỉ dẫn đến một tuổi, với các yếu tố mới d, và sau đó sử dụng sơ đồ mới thay thế. Tệp XSD cũ không bị xúc động; tạo các lớp JAXB mới (làm ví dụ) sẽ dẫn đến mã tương thích ngược.

Vì vậy, XSD-1 sẽ xác nhận một cái gì đó như thế này:

<?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) --> 
<ab xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd"> 
    <a> 
     <aChild>aChild1</aChild> 
    </a> 
    <b> 
     <bChild>1</bChild> 
    </b> 
    <c> 
     <cChild>cChild1</cChild> 
    </c> 
</ab> 

Sample XML for XSD-1

Bạn sẽ cần một cái gì đó như thế này (XSD-2):

<?xml version="1.0" encoding="utf-8" ?> 
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema1.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema1.xsd" xmlns:b="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

    <xsd:import namespace="http://tempuri.org/XMLSchema.xsd" schemaLocation="XSD-1.xsd"/> 

    <xsd:element name="d" substitutionGroup="b:ExtensibleChoice-A" type="dType" block="#all"/> 

    <xsd:complexType name="dType"> 
     <xsd:complexContent> 
      <xsd:extension base="b:ExtensibleChoiceBaseType"> 
       <xsd:sequence> 
        <xsd:element name="dChild" type="xsd:string"/> 
       </xsd:sequence> 
      </xsd:extension> 
     </xsd:complexContent> 
    </xsd:complexType> 
</xsd:schema> 
  • sơ đồ hiển thị danh sách thành viên "mới", d được đánh dấu màu xanh:

Extended substitution group members list

Để xác nhận điều này:

<?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) --> 
<ab xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:d="http://tempuri.org/XMLSchema1.xsd"> 
    <a> 
     <aChild>aChild1</aChild> 
    </a> 
    <d:d> 
     <d:dChild>1</d:dChild> 
    </d:d> 
</ab> 

Sample XML showing the new member

+0

Làm thế nào để thực hiện quyền thừa kế với các nhóm thay thế? – ceving

+0

Bạn có thể giải thích tại sao bạn đang sử dụng chặn thay thế không? – prasopes

+1

@prasopes, không có lý do cụ thể trong trường hợp này. Nó nói chung, nó sẽ phụ thuộc vào những gì bạn đang cố gắng làm. Nếu bạn quan tâm để xem nếu nó áp dụng cho trường hợp của bạn, có một cái nhìn vào những gì nó có nghĩa là (ví dụ như [ở đây] (https://msdn.microsoft.com/en-us/library/ms256118 (v = vs. 110) .aspx)). –

1

Một ví dụ khác với Substitutions.

XSD

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> 
    <xs:element name="root"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="abExtension"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="abExtension" type="abExtensionType"/> 
    <xs:complexType name="abExtensionType"> 
     <xs:choice minOccurs="0" maxOccurs="unbounded"> 
      <xs:element name="a"/> 
      <xs:element name="b"/> 
     </xs:choice> 
    </xs:complexType> 
    <xs:element name="abcExtension" substitutionGroup="abExtension"> 
     <xs:complexType> 
      <xs:complexContent> 
       <xs:extension base="abExtensionType"> 
        <xs:choice minOccurs="0" maxOccurs="unbounded"> 
         <xs:element name="c"/> 
        </xs:choice> 
       </xs:extension> 
      </xs:complexContent> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="abcdExtension" substitutionGroup="abExtension"> 
     <xs:complexType> 
      <xs:complexContent> 
       <xs:extension base="abExtensionType"> 
        <xs:choice minOccurs="0" maxOccurs="unbounded"> 
         <xs:element name="c"/> 
         <xs:element name="d"/> 
        </xs:choice> 
       </xs:extension> 
      </xs:complexContent> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

mẫu XML đó xác nhận với điều này là

abcExtension.xml

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test.xsd"> 
    <abcExtension> 
     <b></b> 
     <a></a> 
     <c></c> 
    </abcExtension> 
</root> 

abcdExtension.xml

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test.xsd"> 
<abcdExtension> 
     <a>text</a> 
     <b>test</b> 
     <d>text</d> 
     <c>text</c> 
    </abcdExtension> 
</root> 

abExtension.xml

 <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test.xsd"> 
<abExtension> 
     <b></b> 
     <a></a> 
    </abExtension> 
</root> 
+0

Câu trả lời của bạn không đáp ứng yêu cầu. Bạn đang thiếu kịch bản mà bạn cần xác thực c - b - a (xem ví dụ ). Bằng cách mở rộng phần tử với lựa chọn, bạn tạo "các ngăn"; kết quả thực sự không phải là lựa chọn đúng, nơi mà nội dung trong loại mở rộng có thể hiển thị trước một loại trong loại cơ sở ... –

+0

@PetruGardea Đồng ý. Tôi chỉ đưa ra ví dụ như OP hỏi về cách sử dụng substitutiongroups trong thiết kế. – user47900

11

Có một cách để làm điều này dựa trên thực tế là lựa chọn trong lựa chọn đóng vai trò là lựa chọn lớn hơn.

Thứ nhất, xác định một nhóm yếu tố, trong đó có một lựa chọn duy nhất từ ​​tất cả các yếu tố trong các yếu tố cơ bản:

<xs:group name="common_ab_elements"> 
    <xs:choice> 
     <xs:element name="a"/> 
     <xs:element name="b"/> 
    </xs:choice> 
</xs:group> 

Sau đó, bạn có thể sử dụng trong định nghĩa của bạn về abElement ở vị trí của yếu tố mà bạn có trước đây:

<xs:complexType name="abType"> 
    <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:group ref="common_ab_elements"/> 
    </xs:choice> 
</xs:complexType> 

Nếu bạn cần một loại mở rộng, sau đó bạn có thể mở rộng sự lựa chọn:

<xs:complexType name="abcType"> 
    <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:group ref="common_ab_elements"/> 
     <xs:element name="c"/> 
    </xs:choice> 
</xs:complexType> 
.210

này tương đương với:

<xs:complexType name="abcType"> 
    <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:choice> 
      <xs:element name="a"/> 
      <xs:element name="b"/> 
     </xs:choice> 
     <xs:element name="c"/> 
    </xs:choice> 
</xs:complexType> 

Và vì bản chất của hoạt động lựa chọn, đây là lần lượt tương đương với:

<xs:complexType name="abcType"> 
    <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:element name="a"/> 
     <xs:element name="b"/> 
     <xs:element name="c"/> 
    </xs:choice> 
</xs:complexType> 

... đó là những gì bạn muốn.

Nếu bạn có thuộc tính, bạn cũng có thể cần phải xác định một lớp cơ sở chung mà bạn có thể mở rộng.Với lược đồ này, chỉ các lớp không có các lớp dẫn xuất mới có các phần tử, vì nó là sự hiện diện của các phần tử trên các phần tử cơ bản buộc phải sắp xếp thứ tự.

Những gì chúng tôi đang thực hiện ở đây là xác định thừa kế các yếu tố lựa chọn riêng biệt với chính cấu trúc phân cấp của phần tử.

0

Nếu tập trung của bạn là trên mở rộng hơn loại thừa kế, một <choice> thể được mở rộng bằng cách xác định lại một <group> như sau:

File "abc.xsd" chứa các giản đồ cơ sở:

<schema 
    xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="any" 
    xmlns:n="any" 
    elementFormDefault="qualified"> 

    <group name="baseGroup"> 
     <choice> 
      <element name="a"/> 
      <element name="b"/> 
      <element name="c"/> 
     </choice> 
    </group> 

    <complexType name="choiceType"> 
     <sequence minOccurs="0" maxOccurs="unbounded"> 
      <group ref="n:baseGroup"/> 
     </sequence> 
    </complexType> 

    <element name="test"> 
     <complexType> 
      <sequence> 
       <element name="sample" type="n:choiceType" maxOccurs="unbounded"/> 
      </sequence> 
     </complexType> 
    </element> 
</schema> 

file "abcdef.xsd" kéo dài tuổi <choice> định nghĩa trong lược đồ cơ sở:

<?xml version="1.0"?> 
<schema 
    xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="any" 
    xmlns:n="any" 
    elementFormDefault="qualified"> 

    <redefine schemaLocation="abc.xsd"> 
     <group name="baseGroup"> 
      <choice> 
       <group ref="n:baseGroup"/> 
        <element name="d"/> 
        <element name="e"/> 
     </choice> 
      </group> 
    </redefine> 
</schema> 

này xác nhận file xml sau, ví dụ:

<?xml version="1.0" encoding="UTF-8"?> 
<test 
    xmlns="any" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="any ../schemas/abcde.xsd"> 

    <sample> 
     <a/> 
     <c/> 
     <b/> 
     <a/> 
    </sample> 

    <sample> 
     <c/> 
</sample> 

    <sample> 
    </sample> 

    <sample> 
     <a/> 
     <e/> 
     <b/> 
     <d/> 
     <a/> 
    </sample> 
</test> 
Các vấn đề liên quan