2010-09-03 26 views
6

Questa porzione XSD stato ottenuto da: http://www.iana.org/assignments/xml-registry/schema/netconf.xsdXSD formattazione <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"/> 

E è il nucleo funzionamento chiamate in NETCONF essere il nodo di un documento XML. Sono curioso di sapere perché non è qualcosa di simile:

<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> 

Il ragionamento è che a # 1 quando si cerca di marshall un fagiolo (in jaxb2) ottengo l'eccezione:

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

ho ho letto più volte l'articolo this e non riesco a capire la differenza, e perché sarebbe il numero 1 vs il numero 2 ...

risposta

1

Una domanda abbastanza complicata. Ci sono molte ragioni per progettare schemi usando tipi piuttosto che elementi (questo approccio è chiamato approccio "alla veneziana" rispetto a "fetta di salame" per l'utilizzo di elementi globali). Uno dei motivi è che i tipi possono essere sottotipizzati e un altro può essere utile avere solo elementi globali che possono essere elementi radice.

Vedere this article per ulteriori dettagli sul lato schema.

Ora, come per la domanda JAXB in particolare. Il problema è che hai creato una classe corrispondente a un tipo e hai provato a serializzarlo. Ciò significa che JAXB conosce il suo modello di contenuto, ma non quello che dovrebbe essere il nome dell'elemento. È necessario collegare il RpcType ad un elemento (JAXBElement), ad esempio:

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

Il ObjectFactory è stato posto nel pacchetto creato da JAXB per voi.

11

Non è ovvio, ti concedo. Si tratta della decisione tipo vs elemento.

Quando si ha qualcosa come

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

Questo è essenzialmente un "tipo anonimo", ed è un tipo che non può mai verificarsi in qualsiasi punto diverso all'interno dell'elemento rpcType. A causa di questa certezza, XJC sa che quel tipo avrà sempre il nome rpcType e quindi genererà un'annotazione @XmlRootElement per esso, con il nome rpcType.

D'altra parte, quando si ha

<xs:complexType name="rpcType"> 

allora questo definisce un tipo riutilizzabile che potrebbero definibili con diversi elementi. Il fatto che nel tuo schema ci si riferisca solo a un elemento è irrilevante. A causa di questa incertezza , XJC copre le sue scommesse e non genera uno @XmlRootElement.

L'implementazione di riferimento JAXB ha un flag XJC proprietario denominato "simple binding mode" che, tra le altre cose, presuppone che lo schema che si sta compilando non verrà mai esteso o combinato con un altro. Ciò gli consente di formulare alcune ipotesi, quindi se vede un numero complexType chiamato solo da uno element, allora genererà spesso @XmlRootElement per esso.

La realtà è piuttosto più sottile e complessa di quella, ma nel 90% dei casi, questa è una spiegazione sufficiente.

+0

Se quando si utilizza la 'modalità di associazione semplice', xsd viene esteso o combinato e un altro elemento radice viene definito con lo stesso tipo (nell'estensione) ci sarà un errore di compilazione XJC, o un errore di runtime o comportamento indeterminato ? – Vihung

1

Vantaggi di Tipi Named

Il vantaggio di uno schema usando tipi globali/named è che i tipi di bambino/sub possono essere creati che si estendono il tipo di genitore.

<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"/> 

Il frammento sopra consentirebbe il seguente tipo di bambino da creare:

<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> 

Impatto sulla JAXB

Un altro aspetto di tipi denominati è che possono essere utilizzati da più elementi :

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

Questo significa t lo schema per il compilatore Java non può semplicemente selezionare uno degli elementi possibili per essere il @XmlRootElement per la classe corrispondente a "rpcType".