2015-04-21 1 views
9

Ich versuche, Klassen von folgenden common.xsd zu generieren, die x.xsd und y.xsd importieren.JAXB Klassengenerierung mit importierten XSD und Bindung

common.xsd ist wie folgt:

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

Ich versuche, eine verbindliche Datei zu verwenden, die eine gemeinsame Schnittstelle an, die durch die erzeugten Klassen implementiert werden soll. Meine Einbindemappe ist wie folgt:

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> 

Ich habe versucht, den Code zu generieren, aber es beschwert sich, dass:

[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 

Wie kann ich die Knoten in den Bindungen Dateien sind tatsächlich in der Definition einzelne externe XSD-Dateien, aber nicht in common.xsd?

+0

Ich musste einige fehlende Teile ausfüllen, um den Testfall in meiner Antwort zu erzeugen. Lassen Sie mich wissen, wenn ich falsche Annahmen über Ihren Anwendungsfall gemacht habe. – vallismortis

+0

Hallo, ich habe ein Kopfgeld für diese Frage eröffnet, aber es ist nicht das gleiche Problem, das ich hatte. Mein Problem kommt mit wsdl2java und Bindungen. Ich habe das Problem mit Hilfe der Antworten gelöst, also werde ich die 50 Punkte auf die richtige Antwort auf Ihr Problem vergeben @vallismortis –

+0

Sorry, @ user3057702 fragte die Frage ... Haben Sie Ihre Antwort gefunden ??? –

Antwort

3

Normalerweise wäre die Verwendung von Schema Component Designators (SCD) anstelle von XPath das, was Sie tun möchten.

Using SCD for customizations

[XPath] ist auch fehleranfällig, weil es Schema Dokumente auf dem Weg beruht angelegt sind, weil das Attribut schema nach rechts Schema Dokument-Datei verweisen muss. Wenn ein Schema zur Modularität in mehrere Dateien aufgeteilt wird (was besonders bei großen Schemas häufig vorkommt), müssen Sie herausfinden, um welche Schemadatei es sich handelt. Auch wenn Sie relative Pfade verwenden können, ist es aufgrund dieser Hartcodierung von Pfadinformationen schwierig, die Bindungsdatei an andere Personen weiterzugeben.

SCD Support

Im Vergleich zur Standard XPath basierten Ansatz ermöglicht SCD robustere und präzise Art und Weise ein Ziel einer Anpassung zu identifizieren. Weitere Informationen zu SCD finden Sie im scd-Beispiel. Beachten Sie, dass SCD ein W3C-Arbeitsentwurf ist und sich möglicherweise in Zukunft ändert.

Leider funktioniert SCD aufgrund einer bug in XJC nicht in Kombination mit Herstellererweiterungen.

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

Die author of jaxb2-basics hat vor kurzem geschrieben, um eine detailed explanation dieser besonderen Problem: Sie wäre ein Fehler, wie zu sehen. Wenn Sie Vendor-Erweiterungen verwenden möchten, bleiben Sie vorerst mit XPath (und seinen Einschränkungen) beschäftigt.

Ein XPath-basierte Lösung

Hier ist ein komplettes, funktionierendes Beispiel XPath mit den Erweiterungen des Herstellers auf der Grundlage der Informationen, die Sie in Ihrer Frage zur Verfügung gestellt. Ich glaube, dass die Klassen aus den importierten Schemas über ein separates Bindungselement ordnungsgemäß generiert werden können. Als Beweis dafür, dass dies wie erwartet funktioniert, ist die Klasse, die aus dieser Bindung generiert wird(), sichtbar und wird von den Klassen wieder verwendet, die von common.xsd generiert wurden. Jede generierte Klasse implementiert die Basisklasse jaxb.BaseMessage.

Ich glaube, das ist so eine gute Lösung wie Sie finden werden, bis der XJC-Fehler behoben ist.

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

Ich habe eine Fütterung Sie sind überkompliziert. Das Problem ist, dass 'schemaLocation' auf das falsche Schema verweist. Ich verstehe nicht, warum SCDs hier wirklich notwendig waren. – lexicore

+1

Ich denke, dass es einen Teil des Anwendungsfalls gibt, den wir hier nicht sehen. Ich habe die Annahme gemacht, dass die 'common.xml' das einzige Schema unter der Kontrolle des Entwicklers sein könnte, und dass potenziell viele andere Schemata enthalten sein könnten, die abgeleiteten Typen alle in der "gemeinsamen" Datei definiert. So wie die Frage formuliert ist, scheint es wünschenswert, nicht direkt auf alle importierten Schemata Bezug zu nehmen. Das ist einer der Fälle, in denen scd verbessert werden sollte. Hoffentlich reagiert OP und wir können den Rest des Anwendungsfalls sehen. – vallismortis

+0

Hm, Sie müssen das Schema nicht "kontrollieren", um Bindings darauf anwenden zu können. Ich habe große Schemakollektionen mit (fast) keinen SCDs zusammengestellt. Ich würde sagen, wir haben genug Hinweise gegeben. Erwarten Sie nicht viel Reaktion von neuen Nutzern mit niedrigen Wiederholungszahlen. – lexicore

-1

Ich denke, es ist nicht, weil Sie den Knoten nicht gestartet funktioniert mit //

Try this:

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

In der Frage wurde 'node ="/xsd: schema "' als Startknoten verwendet. In der Regel wird xsd: complexType [@ name = 'Customer'] 'als untergeordneter Knoten des schema-Elements erwartet. XPath findet sie jedoch nicht beim Importieren von Schemas mit ihren eigenen Namespaces. – vallismortis

2

Ich schreibe eine zweite Antwort, weil ich glaube, dass das, was Sie erreichen wollen, ohne Herstellererweiterungen möglich ist, aber ich denke auch, dass meine ursprüngliche Antwort für andere nützlich sein kann, die Erweiterung benötigen.

In diesem Beispiel werden auch die Namespaces entfernt, sie können jedoch problemlos wieder hinzugefügt werden. Dasselbe Build-Skript wird für diese Antwort wie in meinem vorherigen Skript verwendet.

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

Warum Sie zeigen einfach nicht Ihre schemaLocation-x.xsd und y.xsd, wo die Typen definiert werden?