namespaces - JAXB Impl 在编码的 xml 中生成不正确的命名空间

标签 namespaces jaxb marshalling maven-jaxb2-plugin unmarshalling

我正在使用 JAXB 根​​据定义的模式编码/解码 xml 文档。我注意到 JAXB 在编码的 xml 中生成不正确的 namespace 。

这里是详细信息-

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>

我已经为 jaxbMarshaller 定义了一个 namespacePrefixMapperImpl(在我的 spring 配置中),它将 URI 映射到我定义的前缀名称。

编码的响应 xml 如下所示。请注意,JAXB 在 namespace 前缀上搞砸了。 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>

最佳答案

好吧,看起来 Jaxb 正在为导入的子元素保留包含 xsd 的目标 namespace ,即使那些导入的子元素有自己的 namespace 。解决此问题的一种方法是将架构中导入元素的定义从“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>

关于namespaces - JAXB Impl 在编码的 xml 中生成不正确的命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11962835/

相关文章:

C++:当我在 #include&lt;headerxy> 之前使用 "using namespace xyz"时会发生什么

java - 为什么我的 xpath 不起作用?

java - 使用jaxb读取xml文档

memory - 有人可以解释 Marshal.StructureToPtr

c# - C# 中使用 StyleCop 的命名空间问题

python - xml.etree.ElementTree - 设置 xmlns = '...' 时遇到问题

java - 我想在 CXF codegen 上添加 @XmlRoot 注释

java - 验证 JAXB,但不忽略空格

ruby-on-rails - Ruby On Rails 中的编码与 ActiveRecord 序列化

c# - 使用 LayoutKind.Explicit 进行 boolean 编码,这是按设计损坏还是失败?