JAXB Impl генерирует неправильные пространства имен в упорядоченном xml

Я использую JAXB для маршалинга / демаршалинга XML-документа на основе определенных схем. Я заметил, что JAXB создает неправильные пространства имен в упорядоченном xml.

Вот подробности -

soap.xsd ->

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope" 
    xmlns:svc="http://abc.com/ServiceSetupV001"
    targetNamespace="http://schemas.xmlsoap.org/soap/envelope"
    elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xsd:import namespace="http://abc.com/ServiceSetupV001" schemaLocation="schema1.xsd" />

    <xsd:complexType name="Envelope">
        <xsd:sequence minOccurs="0" maxOccurs="1">
            <xsd:element name="Body" type="soapenv:Body" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="Body">
        <xsd:sequence minOccurs="0" maxOccurs="1">
            <xsd:element name="detailsRequest" type="svc:DetailsRequest" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="detailsResponse" type="svc:DetailsResponse" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
    </xsd:complexType>

</xsd:schema>

schema1.xsd ->

<xsd:schema 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://abc.com/ServiceSetupV001" 
    xmlns:svc="http://abc.com/ServiceSetupV001" 
    xmlns:osa="http://abc.com/xmlschema/osa" 
    elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xsd:import namespace="http://abc.com/xmlschema/osa" schemaLocation="schema2.xsd"/>

    <xsd:complexType name="DetailsRequest">
        <xsd:sequence minOccurs="0" maxOccurs="1">
            <xsd:element name="requestHeader" type="osa:RequestHeader" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="detailsRequest" type="svc:DetailsRequest" />

    <xsd:complexType name="DetailsResponse">
        <xsd:sequence minOccurs="0" maxOccurs="1">
            <xsd:element name="responseHeader" type="osa:ResponseHeader" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="detailsResponse" type="svc:DetailsResponse" />

</xsd:schema>

schema2.xsd ->

 <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:osa="http://abc.com/xmlschema/osa" 
        targetNamespace="http://abc.com/xmlschema/osa" 
        elementFormDefault="qualified" attributeFormDefault="unqualified">

        <xsd:complexType name="RequestHeader">
            <xsd:sequence>
                <xsd:element name="component" type="string" />
                <xsd:element name="channel" type="string" />
                <xsd:element name="serverInstance" type="string" minOccurs="0" />
                <xsd:element name="traceId" type="string" />
                <xsd:element name="applicationId" type="string" />
                <xsd:element name="userId" type="string" minOccurs="0" />
                <xsd:element name="userIdType" type="string" minOccurs="0" />
                <xsd:element name="role" type="string" minOccurs="0" />
                <xsd:element name="timestamp" type="dateTime" minOccurs="0" />
                <xsd:element name="isReplyExpected" type="boolean" minOccurs="0" />
            </xsd:sequence>
        </xsd:complexType>

        <xsd:complexType name="ResponseHeader">
            <xsd:sequence>
                <xsd:element name="component" type="string" />
                <xsd:element ref="osa:service" />
                <xsd:element name="traceId" type="string" />
                <xsd:element name="serverInstance" type="string" />
                <xsd:element name="timestamp" type="dateTime" />
            </xsd:sequence>
        </xsd:complexType>

        <xsd:element name="service" type="osa:Service" />
        <xsd:complexType name="Service">
            <xsd:sequence>
                <xsd:element name="name" type="string" />
                <xsd:element name="operation" type="string" />
                <xsd:element name="version" type="string" />
            </xsd:sequence>
        </xsd:complexType>  

    </xsd:schema>

Я определил namespacePrefixMapperImpl для jaxbMarshaller (в моей конфигурации Spring), который сопоставляет URI с моими определенными именами префиксов.

Упорядоченный ответ xml выглядит так. Обратите внимание, что JAXB допустил ошибку с префиксами пространства имен. JAXB использует пространство имен soapenv для сложного типа detailsResponse вместо префикса svc. Затем он использует префикс svc для сложного типа responseHeader вместо префикса osa. Некоторые элементы имеют строковый тип и поэтому не должны иметь префиксов (т.е. пространство имен по умолчанию). И так далее...

Где я ошибся? Или это проблема с jaxb-impl.

Сгенерированный XML ->

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope"
xmlns:osa="http://abc.com/xmlschema/osa"
xmlns:svc="http://abc.com/ServiceSetupV001">
    <soapenv:Body>
        <soapenv:detailsResponse>
            <svc:responseHeader>
                <osa:component/>
                <osa:service/>
                <osa:traceId>sadasdas</osa:traceId>
                <osa:serverInstance>40d501</osa:serverInstance>
                <osa:timestamp>2012-07-01T02:18:00.693Z</osa:timestamp>
            </svc:responseHeader>
        </soapenv:detailsResponse>
    </soapenv:Body>
</soapenv:Envelope>

Плагин, который я использую для создания классов JAXB из схемы, определен в моем pom.xml следующим образом:

<!-- Plugin to generate jaxb classes from xsd -->
<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.2</version>
    <executions>
        <execution>
            <id>process-xsd</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <phase>generate-sources</phase>
            <configuration>
                <schemaIncludes>
                    <include>**/*.xsd</include>
                </schemaIncludes>
                <bindingIncludes>
                    <include>**/*.xjb</include>
                </bindingIncludes>
                <generateDirectory>${src.dir}</generateDirectory>
                    <verbose>true</verbose>
                <extension>true</extension>
                <args>
                    <arg>-Xannotate</arg>
                </args>
                <plugins>
                    <plugin>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics-annotate</artifactId>
                        <version>0.6.4</version>
                    </plugin>
                </plugins>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2.6</version>
        </dependency>       
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>stax</groupId>
            <artifactId>stax-api</artifactId>
            <version>1.0.1</version>
        </dependency>
        <dependency>
            <groupId>activesoap</groupId>
            <artifactId>jaxb-xercesImpl</artifactId>
            <version>1.5</version>
        </dependency>                   
    </dependencies>             
</plugin>

person pfl    schedule 15.08.2012    source источник


Ответы (1)


Что ж, похоже, Jaxb сохраняет целевое пространство имен содержащего xsd для импортированных дочерних элементов, даже если эти импортированные дочерние элементы имеют собственное пространство имен. Один из способов исправить это - изменить определение импортируемого элемента в схеме с «type» на «ref».

Но в этом случае я не хочу изменять схемы в том виде, в котором они исходят от клиента, и поэтому мы не хотим изменять их, чтобы они работали.

Поэтому я добавил аннотации ниже в свой файл bindings.xjb. Теперь я вижу, что элементы в сгенерированных классах схемы имеют правильное объявление пространства имен. Но теперь проблема в том, что сгенерированный xml не создает дочерние элементы, даже если пространство имен теперь правильное.

Итак, я снова застрял. Я не думал, что это будет так сложно.

Изменения в моем bindings.xjb:

<jaxb:bindings node="//xsd:complexType[@name='Body']//xsd:element[@name='detailsRequest']">
    <annox:annotate target="field">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" 
        name="detailsRequest" 
        namespace="http://abc.com/ServiceSetupV001"/>
    </annox:annotate>            
<jaxb:bindings node="//xsd:complexType[@name='Body']//xsd:element[@name='detailsResponse']">
    <annox:annotate target="field">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" 
        name="detailsResponse" 
        namespace="http://abc.com/ServiceSetupV001"/>
    </annox:annotate>            
</jaxb:bindings>        

<jaxb:bindings node="//xsd:complexType[@name='DetailsRequest']//xsd:element[@name='requestHeader']">
    <annox:annotate target="field">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" 
        name="requestHeader" 
        namespace="http://abc.com/xmlschema/osa"/>
    </annox:annotate>            
<jaxb:bindings node="//xsd:complexType[@name='DetailsResponse']//xsd:element[@name='responseHeader']">
    <annox:annotate target="field">
    <annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" 
        name="responseHeader" 
        namespace="http://abc.com/xmlschema/osa"/>
    </annox:annotate>            
</jaxb:bindings>

Сгенерированные классы имеют соответствующие аннотации пространств имен

@XmlElement(name = "detailsRequest", namespace = "http://abc.com/ServiceSetupV001")
protected DetailsRequest detailsRequest;

@XmlElement(name = "detailsResponse", namespace = "http://abc.com/ServiceSetupV001")
protected DetailsResponse detailsResponse;

Но теперь упорядоченный XML не имеет значений

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope"
xmlns:osa="http://abc.com/xmlschema/osa"
xmlns:svc="http://abc.com/ServiceSetupV001">
    <soapenv:Body>
        <svc:detailsResponse/>
    </soapenv:Body>
</soapenv:Envelope>
person pfl    schedule 15.08.2012