Java 具有不同名称空间的JAXB片段

Java 具有不同名称空间的JAXB片段,java,jaxb,marshalling,Java,Jaxb,Marshalling,我必须整理根xml对象的一个片段: Header header = ebicsNoPubKeyDigestsRequest.getHeader(); JAXBElement<org.ebics.h003.EbicsNoPubKeyDigestsRequest.Header> jaxbElement = new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>( new QName("header"), EbicsN

我必须整理根xml对象的一个片段:

Header header = ebicsNoPubKeyDigestsRequest.getHeader();
JAXBElement<org.ebics.h003.EbicsNoPubKeyDigestsRequest.Header> jaxbElement =
  new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>(
    new QName("header"), EbicsNoPubKeyDigestsRequest.Header.class, header);
byte[] headerXml = JAXBHelper.marshall(jaxbElement, true);
编辑:这里是不同的包-info.java:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.ebics.org/H003", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.ebics.h003;

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.ebics.org/S001", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.ebics.s001;

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.w3.org/2000/09/xmldsig#", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.w3._2000._09.xmldsig_;

在没有看到实际的XML模式、文件和JAXB生成的类(及其注释)的情况下,我只能建议您尝试根据您的场景调整以下示例

假设您有一个JAXB生成的类,如下所示:

@XmlRootElement(namespace = "http://test.com")
@XmlType(namespace = "http://test.com")
public static final class Test {

  public String data;

  public Test() {}
}
它位于包
test
中,其中有一个
package info.java
文件,如下所示:

@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED,
           xmlns = @XmlNs(prefix = "", namespaceURI = "http://test.com"))
package test;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
JAXBContext context =
  JAXBContext.newInstance("org.ebics.h003:org.ebics.s001:org.w3._2000._09.xmldsig");
QName qualifiedName = new QName("http://www.ebics.org/H003", "header");
JAXBElement<EbicsNoPubKeyDigestsRequest.Header> header =
    new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>(
        qualifiedName, EbicsNoPubKeyDigestsRequest.Header.class, header);
以下代码:

Test test = new Test();
test.data = "Hello, World!";

JAXBContext context = JAXBContext.newInstance(Test.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(test, System.out);
将打印以下内容:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<test xmlns="http://test.com">
    <data>Hello, World!</data>
</test>
在此之后,您将创建
JAXBContext
,如下所示:

@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED,
           xmlns = @XmlNs(prefix = "", namespaceURI = "http://test.com"))
package test;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
JAXBContext context =
  JAXBContext.newInstance("org.ebics.h003:org.ebics.s001:org.w3._2000._09.xmldsig");
QName qualifiedName = new QName("http://www.ebics.org/H003", "header");
JAXBElement<EbicsNoPubKeyDigestsRequest.Header> header =
    new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>(
        qualifiedName, EbicsNoPubKeyDigestsRequest.Header.class, header);
(我注意到您没有实际使用
h000
包,因此我在包名列表中省略了它。如果包含它,则封送XML的根标记可能会包含其名称空间和前缀映射,即使没有使用它)

在此之后,您将解组输入XML,并对内存中的对象执行任何您想要的操作

Unmarshaller unmarshaller = context.createUnmarshaller();

EbicsNoPubKeyDigestsRequest ebicsNoPubKeyDigestsRequest =
    (EbicsNoPubKeyDigestsRequest) unmarshaller.unmarshal(stream);
现在,如果您只想整理嵌套在
ebicsnopubKeyDigestRequest
中的
header
标记,则必须将其包装在
JAXBElement
中,因为
header
的类型
ebicsnopubKeyDigestRequest.header
没有使用
@XmlRootElement
注释进行注释。创建此元素有两种方法(在本例中为一种)

为相应的包创建一个
ObjectFactory
实例,并使用其
JAXBElement createT(T)
函数。它将其输入包装成一个
JAXBElement
。然而,不幸的是,对于
字段的类型(给定您的模式文件),XJC没有生成这样的方法,因此您必须手动执行

基本上,您几乎做对了,但是当创建
JAXBElement
而不是传递它
newqname(“header”)
时,您必须创建一个完全限定的名称,这意味着也指定了名称空间。仅传递XML标记的名称是不够的,因为JAXB不会通过这种方式知道这个特定的
标记是
的一部分http://www.ebics.org/H003“
名称空间。这样做:

@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED,
           xmlns = @XmlNs(prefix = "", namespaceURI = "http://test.com"))
package test;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
JAXBContext context =
  JAXBContext.newInstance("org.ebics.h003:org.ebics.s001:org.w3._2000._09.xmldsig");
QName qualifiedName = new QName("http://www.ebics.org/H003", "header");
JAXBElement<EbicsNoPubKeyDigestsRequest.Header> header =
    new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>(
        qualifiedName, EbicsNoPubKeyDigestsRequest.Header.class, header);
QName qualifiedName=新的QName(“http://www.ebics.org/H003“,”标题“);
JAXBElement收割台=
新雅克斯贝尔蒙酒店(
限定名称,EBICSNOPubKeyDigestRequest.Header.class,Header);

我没有测试是否只更改
QName
实例化就能解决您的问题,但可能会。但是我认为不会,您必须手动管理前缀以获得一个好的、一致的结果。

我假设包
org.ebics.h003
,其中的所有类都是由XJC生成的。如果是,那么如果包中有一个名为
package info.java
的文件,您是否可以发布该文件以及(顶部显示
@XmlRootElement
@XmlType
等注释)您的
ebicsnopubKeyDigestRequest
ebicsnopubKeyDigestRequest.Header
类的名称?@javax.xml.bind.annotation.XmlSchema(namespace=“”,elementFormDefault=javax.xml.bind.annotation.XmlNsForm.QUALIFIED)包org.ebics.h003;=>h003@javax.xml.bind.annotation.XmlSchema(namespace=”“,elementFormDefault=javax.xml.bind.annotation.XmlNsForm.QUALIFIED)包org.ebics.s001;=>s001@javax.xml.bind.annotation.XmlSchema(namespace=“”,elementFormDefault=javax.xml.bind.annotation.XmlNsForm.QUALIFIED)包org.w3.\u 2000.\u 09.xmldsig;=>W3C您可以将此作为问题的更新发布,以提高可读性。请下次使用编辑功能。另外,类上的注释也会很有用。您为我们提供了一个指向包含模式文件的zip文件的链接(在我的答案的注释部分),但这些似乎反映了您在示例中显示的模式文件的另一个版本(H004而不是H003)。无论如何,我无法用XJC编译模式。如果您告诉我们您是如何编译它的,那么我们可以更快(可能)解决这个问题。对不起!我使用较旧的模式版本(适用于法国):谢谢,但我不能修改从这个xsd:生成的类,但也许我可以使用xjb文件更改注释?@Baptiste我只要求您发布您的类,看看它们是否有任何注释(是的,类文件生成可以通过绑定配置进行操作)。我会为自己生成类,看看我能做些什么。如果你能告诉我们你是如何用XJC编译这些模式文件的,那将很有帮助。非常感谢,我只是从jaxb开始,我不明白everything@KohányiRóbert在解组时是否也有同样的效果?i、 e.XML到Java对象?@ziggy我不太确定你在说什么,同样的工作,我也没有我的测试项目用于我的答案了。。。但是,如果您可以将Java对象打包成与问答中的XML格式类似的XML格式,那么我认为您也可以将这样的XML分解成Java对象。如果出于某种原因这不起作用,那么我打赌是因为XJC没有/无法从提供的XSD正确生成Java类(正如我在回答中提到的)。我希望这有帮助。