2015-04-21 9 views
9

Sto cercando di generare classi dal seguente common.xsd che importa x.xsd e y.xsd.Generazione classe JAXB con XSD importato e rilegatura

common.xsd è la seguente:

<?xml version="1.0"?> 
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:import namespace="mynamespace:x" schemaLocation="x.xsd"/> 
    <xs:import namespace="mynamespace:y" schemaLocation="y.xsd"/> 
</xs:schema> 

cerco di usare un file di legame che specifica un'interfaccia comune che deve essere attuato dalle classi generate. Il mio file di collegamento è la seguente:

jaxb:extensionBindingPrefixes="inheritance" version="2.1"> 

<jaxb:globalBindings> 
    <jaxb:javaType name="java.lang.Long" xmlType="xsd:integer"/> 
</jaxb:globalBindings> 

<jaxb:bindings schemaLocation="common.xsd" node="/xsd:schema"> 

    <jaxb:bindings node="xsd:complexType[@name='Customer']"> 
     <inheritance:implements>jaxb.BaseMessage</inheritance:implements> 
     <jaxb:class /> 
    </jaxb:bindings> 

    <jaxb:bindings node="xsd:complexType[@name='Payments']"> 
     <inheritance:implements>jaxb.BaseMessage</inheritance:implements> 
     <jaxb:class /> 
    </jaxb:bindings> 

Ho provato a generare il codice, ma si lamenta che:

[ERROR] XPath evaluation of "xsd:complexType[@name='Customer']" results in empty target node 
[ERROR] XPath evaluation of "xsd:complexType[@name='Payments']" results in empty target node 

Come posso definire i nodi del binding file sono effettivamente in singoli file XSD esterni ma non in common.xsd?

+0

Ho dovuto compilare alcuni pezzi mancanti per produrre il test case nella mia risposta. Fammi sapere se ho fatto ipotesi errate sul tuo caso d'uso. – vallismortis

+0

Ciao, ho aperto una taglia per questa domanda, ma non è lo stesso problema che ho avuto. Il mio problema si presenta quando si utilizza wsdl2java e binding. Ho risolto il problema con l'aiuto delle risposte, quindi assegnerò i 50 punti alla risposta corretta al tuo problema @vallismortis –

+0

scusa, @ utente3057702 ha posto la domanda ... Hai trovato la risposta ??? –

risposta

3

Normalmente, il modo in cui si vorrebbe farlo sarebbe utilizzare Schema Component Designators (SCD) anziché XPath.

Using SCD for customizations

[XPath] è anche soggetto a errori, perché si basa sul modo in cui i documenti dello schema sono disposte, poiché l'attributo schemaLocation deve puntare al file documento di schema a destra. Quando uno schema è suddiviso in più file per modularità (accade soprattutto spesso con schemi di grandi dimensioni), allora dovresti trovare il file di schema che è. Anche se è possibile utilizzare percorsi relativi, questo hard-coding delle informazioni sul percorso rende difficile il passaggio del file di bind alle altre persone.

SCD Support

Rispetto al metodo standard basato XPath, SCD consente modo più robusto e concisa di identificazione di un bersaglio di una personalizzazione. Per ulteriori informazioni su SCD, consultare l'esempio scd. Si noti che SCD è una bozza di lavoro W3C e potrebbe cambiare in futuro.

Sfortunatamente, a causa di uno bug in XJC, SCD non funziona in combinazione con le estensioni del fornitore. Si potrebbe vedere un errore del tipo:

[ERROR] cvc-elt.1: Cannot find the declaration of element 'inheritance:implements'. 

Il author of jaxb2-basics ha recentemente scritto un detailed explanation di quel particolare problema. In sostanza, se si desidera utilizzare le estensioni del fornitore, per ora si è bloccato con XPath (e le sue limitazioni).

soluzione

Ecco un XPath-based è un esempio di lavoro completo utilizzando XPath con le estensioni del fornitore sulla base delle informazioni che hai fornito nella sua interrogazione. Credo che il modo corretto per generare le classi dagli schemi importati sia tramite un elemento di binding separato. A riprova che ciò funziona come previsto, la classe generata da questa associazione (Cust) è visibile e riutilizzata dalle classi generate da common.xsd. Ogni classe generata implementa la classe base jaxb.BaseMessage.

Credo che questa sia la soluzione migliore che troverete finché il bug XJC non viene risolto.

src/main/resources/bindings.xjb:

<?xml version="1.0" encoding="UTF-8"?> 
<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    jaxb:version="2.1" 
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
    xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" 
    jaxb:extensionBindingPrefixes="xjc inheritance"> 

    <jaxb:globalBindings> 
    <jaxb:javaType name="java.lang.Long" xmlType="xsd:integer" /> 
    </jaxb:globalBindings> 

    <jaxb:bindings schemaLocation="schema/x.xsd"> 
    <jaxb:bindings node="//xsd:complexType[@name='Customer']"> 
     <jaxb:class name="Cust" /> 
     <inheritance:implements>jaxb.BaseMessage</inheritance:implements> 
    </jaxb:bindings> 
    </jaxb:bindings> 

    <jaxb:bindings schemaLocation="schema/y.xsd"> 
    <jaxb:bindings node="//xsd:complexType[@name='Payments']"> 
     <jaxb:class /> 
     <inheritance:implements>jaxb.BaseMessage</inheritance:implements> 
    </jaxb:bindings> 
    </jaxb:bindings> 

    <jaxb:bindings schemaLocation="schema/common.xsd"> 
    <jaxb:bindings node="//xsd:complexType[@name='CustomerPayments']"> 
     <jaxb:class /> 
     <inheritance:implements>jaxb.BaseMessage</inheritance:implements> 
    </jaxb:bindings> 
    </jaxb:bindings> 

</jaxb:bindings> 

src/main/resources/schema/common.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema version="1.0" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:x="http://test.org/common/x" 
    xmlns:y="http://test.org/common/y" 
    targetNamespace="http://test.org/common"> 

    <xsd:import namespace="http://test.org/common/x" schemaLocation="x.xsd" /> 
    <xsd:import namespace="http://test.org/common/y" schemaLocation="y.xsd" /> 

    <xsd:complexType name="CustomerPayments"> 
    <xsd:sequence> 
     <xsd:element name="customer" type="x:Customer" /> 
     <xsd:element name="payments" type="y:Payments" /> 
    </xsd:sequence> 
    </xsd:complexType> 

</xsd:schema> 

src/main/resources/schema/x.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema version="1.0" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified" 
    attributeFormDefault="unqualified" 
    targetNamespace="http://test.org/common/x"> 

    <xsd:complexType name="Customer"> 
    <xsd:sequence> 
     <xsd:element name="name" type="xsd:string" /> 
    </xsd:sequence> 
    </xsd:complexType> 

</xsd:schema> 

src/main/resources/schema/y.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema version="1.0" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified" 
    attributeFormDefault="unqualified" 
    targetNamespace="http://test.org/common/y"> 

    <xsd:complexType name="Payments"> 
    <xsd:sequence> 
     <xsd:element name="amount" type="xsd:float" /> 
    </xsd:sequence> 
    </xsd:complexType> 

</xsd:schema> 

build.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE project> 
<project name="JAXB XPath Test" default="xjc" basedir="."> 

    <property name="build.folder" location="build" /> 

    <taskdef name="xjc" classname="org.jvnet.jaxb2_commons.xjc.XJC2Task"> 
    <classpath> 
     <fileset dir="${basedir}/lib"> 
      <include name="jaxb-impl-2.2.6.jar" /> 
      <include name="jaxb-xjc-2.2.6.jar" /> 
      <include name="jaxb2-basics-ant-0.9.4.jar" /> 
      <include name="javaparser-1.0.11.jar" /> 
      <include name="commons-lang3-3.2.jar" /> 
     </fileset> 
    </classpath> 
    </taskdef> 

    <target name="xjc" description="Generate the source code."> 

    <xjc destdir="${basedir}/src/main/java" extension="true"> 

     <arg line=" 
     -Xequals 
     -XhashCode 
     -XtoString 
     -Xcopyable 
     -Xmergeable 
     -Xinheritance" /> 

     <binding dir="${basedir}/src/main/resources"> 
     <include name="**/*.xjb" /> 
     </binding> 

     <schema dir="${basedir}/src/main/resources/schema"> 
     <include name="**/*.xsd" /> 
     </schema> 

     <classpath> 
     <fileset dir="${basedir}/lib"> 
      <include name="jaxb2-basics-0.9.4.jar"/> 
      <include name="jaxb2-basics-runtime-0.9.4.jar"/> 
      <include name="jaxb2-basics-tools-0.9.4.jar"/> 
      <include name="commons-beanutils-1.8.0.jar"/> 
      <include name="commons-lang3-3.2.jar"/> 
      <include name="commons-logging-1.1.1.jar"/> 
     </fileset> 
     </classpath> 

    </xjc> 

    </target> 

</project> 
+0

Ho un feedling che stai complicando eccessivamente. Il problema è che 'schemaLocation' punta allo schema sbagliato. Non vedo perché le SCD fossero veramente necessarie qui. – lexicore

+1

Penso che ci possa essere una parte del caso d'uso che non stiamo vedendo qui. Ho fatto l'ipotesi che il 'common.xml' potrebbe essere l'unico schema sotto il controllo dello sviluppatore e che potrebbero esserci potenzialmente molti altri schemi inclusi, i tipi derivati ​​tutti definiti nel file "comune". Il modo in cui la domanda è formulata, sembra che sia preferibile non fare riferimento direttamente a tutti gli schemi importati. Questo è uno dei casi in cui SCD è stato progettato per migliorare. Speriamo che OP risponda e possiamo vedere il resto del caso d'uso. – vallismortis

+0

Hm, non è necessario "controllare" lo schema per poter applicare i collegamenti ad esso. Ho compilato grandi collezioni di schemi con (quasi) nessun SCD. Direi che abbiamo fornito abbastanza suggerimenti. Non aspettarti molte reazioni da parte dei nuovi utenti a basso profilo. – lexicore

-1

penso che non funziona perché non è stato avviato il nodo con //

Prova questa:

<jaxb:bindings node="//xsd:complexType[@name='Customer']"> 
    <inheritance:implements>jaxb.BaseMessage</inheritance:implements> 
</jaxb:bindings> 
+2

Nella domanda, 'node ="/xsd: schema "' è stato utilizzato come nodo di partenza. In genere, 'xsd: complexType [@ name = 'Customer']' dovrebbe essere un nodo figlio dell'elemento schema. Tuttavia, XPath non li trova durante l'importazione da schemi utilizzando i propri spazi dei nomi. – vallismortis

2

Sto postando una seconda risposta perché credo che ciò che stai cercando di ottenere sia possibile senza estensioni del venditore, ma penso anche che la mia risposta originale possa essere utile per gli altri che hanno bisogno di estensioni del venditore.

Questo esempio rimuove anche gli spazi dei nomi, ma è possibile aggiungerli facilmente. Lo stesso script di compilazione è usato per questa risposta come nella mia precedente.

src/main/resources/bindings.xjb:

<?xml version="1.0" encoding="UTF-8"?> 
<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    jaxb:version="2.1" 
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
    jaxb:extensionBindingPrefixes="xjc" 
    xmlns:common="schema/common.xsd"> 

    <jaxb:globalBindings> 
    <jaxb:javaType name="java.lang.Long" xmlType="xsd:integer" /> 
    <xjc:superInterface name="jaxb.BaseMessage" /> 
    </jaxb:globalBindings> 

</jaxb:bindings> 

src/main/resources/schema/common.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

    <xsd:include schemaLocation="x.xsd" /> 
    <xsd:include schemaLocation="y.xsd" /> 

    <xsd:complexType name="CustomerPayments"> 
    <xsd:sequence> 
     <xsd:element name="customer" type="Customer" /> 
     <xsd:element name="payments" type="Payments" /> 
    </xsd:sequence> 
    </xsd:complexType> 

</xsd:schema> 

src/main/resources/schema/x.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <xsd:complexType name="Customer"> 
     <xsd:sequence> 
     <xsd:element name="name" type="xsd:string" /> 
     </xsd:sequence> 
    </xsd:complexType> 
</xsd:schema> 

src/main/resources/y.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <xsd:complexType name="Payments"> 
     <xsd:sequence> 
     <xsd:element name="amount" type="xsd:float" /> 
     </xsd:sequence> 
    </xsd:complexType> 
</xsd:schema> 
1

Perché non basta puntare il schemaLocation-x.xsd e y.xsd, in cui sono definiti i tipi?

<jaxb:bindings schemaLocation="x.xsd" node="/xsd:schema"> 
    <jaxb:bindings node="xsd:complexType[@name='Customer']"> 
     <inheritance:implements>jaxb.BaseMessage</inheritance:implements> 
     <jaxb:class /> 
    </jaxb:bindings> 
</jaxb:bindings> 

<jaxb:bindings schemaLocation="y.xsd" node="/xsd:schema"> 
    <jaxb:bindings node="xsd:complexType[@name='Payments']"> 
     <inheritance:implements>jaxb.BaseMessage</inheritance:implements> 
     <jaxb:class /> 
    </jaxb:bindings> 
</jaxb:bindings>