2010-09-03 6 views
6

phần XSD này được lấy từ: http://www.iana.org/assignments/xml-registry/schema/netconf.xsdXSD Formatting <element><complexType> vs <complexType /><element/>

<xs:complexType name="rpcType"> 
    <xs:sequence> 
    <xs:element ref="rpcOperation"/> 
    </xs:sequence> 
    <xs:attribute name="message-id" type="messageIdType" use="required"/> 
    <xs:anyAttribute processContents="lax"/> 
</xs:complexType> 
<xs:element name="rpc" type="rpcType"/> 

Và là cốt lõi để hoạt cuộc gọi trong NETCONF là nút của một tài liệu XML. Tôi tò mò là tại sao nó không phải là một cái gì đó như:

<xs:element name="rpcType"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element ref="rpcOperation"/> 
    </xs:sequence> 
    <xs:attribute name="message-id" type="messageIdType" use="required"/> 
    <xs:anyAttribute processContents="lax"/> 
    </xs:complexType> 
</xs:element> 

Lý do là trong # 1 khi cố gắng marshall một bean (trong jaxb2) tôi nhận được ngoại lệ:

[com.sun.istack.SAXException2: unable to marshal type "netconf.RpcType" as an element because it is missing an @XmlRootElement annotation] 

Tôi có đã đọc được this bài viết hết lần này đến lần khác, và thực sự không thể giữ được sự khác biệt, và tại sao nó lại là số 1 và số 2 ...

Trả lời

1

Khá một câu hỏi liên quan. Có nhiều lý do để thiết kế các lược đồ bằng cách sử dụng các loại thay vì các phần tử (cách tiếp cận này được gọi là phương pháp "mù ven" so với "salami slice" để sử dụng các phần tử toàn cục). Một trong những lý do là các kiểu có thể được đánh máy phụ và một loại khác có thể hữu ích để chỉ có các phần tử toàn cục có thể là các phần tử gốc.

Xem this article để biết thêm chi tiết về phía lược đồ.

Bây giờ, đối với câu hỏi JAXB nói riêng. Vấn đề là bạn đã tạo một lớp tương ứng với một loại và cố gắng nối tiếp nó. Điều đó có nghĩa là JAXB biết mô hình nội dung của nó, nhưng không phải là tên của phần tử. Bạn cần phải đính kèm RpcType của bạn đến một phần tử (JAXBElement), ví dụ:

marshaller.marshal(new ObjectFactory().createRpc(myRpcType)); 

Các ObjectFactory đã được đặt vào các gói được tạo ra bởi JAXB cho bạn.

11

Không rõ ràng, tôi sẽ cấp cho bạn. Nó đi xuống quyết định kiểu vs yếu tố.

Khi bạn có một cái gì đó giống như

<xs:element name="rpcType"> 
    <xs:complexType> 

Đây thực chất là một "loại vô danh", và là một loại mà không bao giờ có thể xảy ra bất cứ nơi nào khác hơn là bên trong phần tử rpcType. Do sự chắc chắn này, XJC biết rằng loại đó sẽ luôn có tên rpcType và do đó tạo ra một chú thích @XmlRootElement cho nó, với tên rpcType.

Mặt khác, khi bạn có

<xs:complexType name="rpcType"> 

thì đây định nghĩa một loại tái sử dụng mà khả năng có thể được gọi bởi các yếu tố khác nhau. Thực tế là trong lược đồ của bạn, nó chỉ được đề cập bởi một phần tử là không liên quan. Bởi vì điều này không chắc chắn, XJC đặt cược cược của nó và không tạo ra một @XmlRootElement.

Triển khai tham chiếu JAXB có cờ XJC độc quyền được gọi là "simple binding mode", trong số những thứ khác, giả định rằng lược đồ bạn đang biên dịch sẽ không bao giờ được mở rộng hoặc kết hợp với nhau. Điều này cho phép nó đưa ra các giả định nhất định, vì vậy nếu nó nhìn thấy một tên complexType chỉ được sử dụng bởi một element, thì nó thường sẽ tạo ra @XmlRootElement cho nó.

Thực tế là khá tinh tế và phức tạp hơn thế, nhưng trong 90% trường hợp, đây là một lời giải thích đầy đủ.

+0

Nếu khi sử dụng 'chế độ ràng buộc đơn giản', xsd được mở rộng hoặc kết hợp và một phần tử gốc khác được định nghĩa cùng loại (trong phần mở rộng) sẽ có lỗi thời gian biên dịch XJC hoặc lỗi thời gian chạy hoặc hành vi không xác định ? – Vihung

1

Ưu điểm của tên loại

Ưu điểm của một sơ đồ sử dụng toàn cầu/tên loại là loại con/phụ có thể được tạo ra mà mở rộng các loại cha mẹ.

<xs:complexType name="rpcType"> 
    <xs:sequence> 
     <xs:element ref="rpcOperation"/> 
    </xs:sequence> 
    <xs:attribute name="message-id" type="messageIdType" use="required"/> 
    <xs:anyAttribute processContents="lax"/> 
</xs:complexType> 
<xs:element name="rpc" type="rpcType"/> 

Đoạn trên sẽ cho phép loại con sau được tạo ra:

<xs:complexType name="myRPCType"> 
    <xs:complexContent> 
     <xs:extension base="rpcType"> 
      <xs:sequence> 
       <xs:element name="childProperty" type="xs:string"/> 
      </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 

Tác động đến JAXB

Một khía cạnh khác của các loại tên là họ có thể được sử dụng bởi nhiều yếu tố :

<xs:element name="FOO" type="rpcType"/> 
<xs:element name="BAR" type="rpcType"/> 

Điều này có nghĩa là t hat lược đồ để trình biên dịch Java không thể chỉ đơn giản là chỉ cần chọn một trong các yếu tố có thể là @XmlRootElement cho lớp tương ứng với "rpcType".