2011-12-19 99 views
3

我不得不马歇尔我的根XML对象的片段JAXB片段:具有不同的命名空间

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); 

但是当我马歇尔ebicsNoPubKeyDigestsRequest的命名空间是不相同的(在报头片段我有:xmlns:ns4="http://www.ebics.org/H003"但在ebicsNoPubKeyDigestsRequest我有xmlns="http://www.ebics.org/H003"

如果我马歇尔直接标题对象,而无需使用的JAXBElement,我有一个No @XmlRootElement错误

怎样才可以有相同的N amespaces? 注:我已经使用了一个NamespacePrefixMapper类:

marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() { 

    @Override 
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { 
    if (namespaceUri.equals("http://www.ebics.org/H003")) { 
     return ""; 
    } else if (namespaceUri.equals("http://www.w3.org/2000/09/xmldsig#")) { 
     return "ds"; 
    } else if (namespaceUri.equals("http://www.ebics.org/S001")) { 
     return "ns1"; 
    } else if (namespaceUri.equals("http://www.w3.org/2001/XMLSchema-instance")) { 
     return "ns2"; 
    } 
    return ""; 
    } 
}); 

编辑:这里的不同package-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_; 
+0

我假定包org.ebics.h003和其中的所有类都是由XJC生成的。如果是,那么如果包内有一个名为'package-info.java'的文件,你可以将它和(* top part *,显示'@ XmlRootElement','@ XmlType'等注释)你的'EbicsNoPubKeyDigestsRequest'和'EbicsNoPubKeyDigestsRequest.Header'类? – 2011-12-19 11:54:39

+0

@ javax.xml.bind.annotation.XmlSchema(namespace =“http://www.ebics.org/H003”,elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package org.ebics.h003; => H003 @ javax.xml.bind.annotation.XmlSchema(命名空间= “http://www.ebics.org/S001”,将elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 包有机ebics.s001; => 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_; => w3 – Baptiste 2011-12-19 12:22:20

+0

您可以发布此更新以提高可读性。请在下次使用编辑功能。此外,您的课堂上的注释也是有用的。 – 2011-12-19 12:32:41

回答

4

没有看到实际的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; 

下面的代码:

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> 

您完全可能完全忽略了NamespacePrefixMapper实现。

玩忽略任何注释中特定的namespace元素,看看输出如何变化。

Blaise Doughan(一个Java XML绑定专家,可能潜伏在某处附近)公布关于在他的博客这个问题的一些信息,请参阅his post一些更深入的了解。


基于Baptiste在聊天中提供的输入,我提出了以下解决方案(我认为这是最无痛的)。

通常用XJC编译模式文件($ xjc .)。这将为每个生成的包生成package-java.info文件。我假设这个模式并没有每天更新,所以你可以安全地对package-info.java文件进行修改(即使这些文件中会有一些行注释,告诉你不要这样做 - 无论如何)。如果架构得到更新并且必须重新编译,则运行带有-npa开关的XJC,它告诉它不要自动生成这些package-info.java文件,因此(理想情况下)您无法覆盖手动创建的文件(如果使用版本控制你可以/应该将这些(手工制作的)文件包含在存储库中)。

根据提供的模式文件生成四个软件包,所以我将包含我的版本的修改后的package-info.java文件。

@XmlSchema(namespace = "http://www.ebics.org/H000", 
      xmlns = @XmlNs(prefix = "ns1", 
          namespaceURI = "http://www.ebics.org/H000")) 
package org.ebics.h000; 

@XmlSchema(namespace = "http://www.ebics.org/H003", 
      xmlns = @XmlNs(prefix = "", 
          namespaceURI = "http://www.ebics.org/H003")) 
package org.ebics.h003; 

@XmlSchema(namespace = "http://www.ebics.org/S001", 
      xmlns = @XmlNs(prefix = "ns3", 
          namespaceURI = "http://www.ebics.org/S001")) 
package org.ebics.s001; 

@XmlSchema(namespace = "http://www.w3.org/2000/09/xmldsig#", 
      xmlns = @XmlNs(prefix = "ns2", 
          namespaceURI = "http://www.w3.org/2000/09/xmldsig#")) 
package org.w3._2000._09.xmldsig; 

在这之后您创建JAXBContext这样的:

JAXBContext context = 
    JAXBContext.newInstance("org.ebics.h003:org.ebics.s001:org.w3._2000._09.xmldsig"); 

(我注意到,你不实际使用使用h000封装所以我从包名称中省略它如果包含,则编组的XML根标签可能会包含它的名称空间和前缀映射,即使它很难被使用。)

在此之后,您将解析您的输入XML和d o无论你想在记忆中的对象。现在

Unmarshaller unmarshaller = context.createUnmarshaller(); 

EbicsNoPubKeyDigestsRequest ebicsNoPubKeyDigestsRequest = 
    (EbicsNoPubKeyDigestsRequest) unmarshaller.unmarshal(stream); 

,如果你想马歇尔只有header标签被嵌套在该ebicsNoPubKeyDigestsRequest,你必须把它包装一个JAXBElement<...>里面,因为header的类型EbicsNoPubKeyDigestsRequest.Header不与@XmlRootElement注解。你有两个(在这个的情况下一个)的方式来创建这个元素。

为相应的包创建一个ObjectFactory实例并使用它的JAXBElement<T> createT(T t)函数。其中包含输入到JAXBElement<...>。不幸的是,对于header字段的类型(给定您的模式文件),XJC不会生成这样的方法,因此您必须手动完成。

基本上你已经差不多完成了它,但是当创建JAXBElement<...>而不是传递new QName("header")时,必须创建一个完全限定名称,这意味着该名称空间也已指定。只传递XML标签的名称是不够的,因为JAXB不会以这种方式知道这个特定的header标签是"http://www.ebics.org/H003"名称空间的一部分。所以,像这样做:

QName qualifiedName = new QName("http://www.ebics.org/H003", "header"); 
JAXBElement<EbicsNoPubKeyDigestsRequest.Header> header = 
    new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>(
     qualifiedName, EbicsNoPubKeyDigestsRequest.Header.class, header); 

如果只改变QName实例解决您的问题,我没有测试,但也许会的。不过,我认为它不会和你必须手动管理你的前缀,以获得不错的一致的结果。

+0

谢谢,但我不能从这个xsd修改生成的类: http://www.ebics.org/fileadmin/unsecured/specification/schema_current/ebics_xml_schema-12-07-2011.zip,但也许我可以用xjb文件更改注释? – Baptiste 2011-12-19 12:34:10

+0

@Baptiste我只要求你发布你的类,看他们是否有任何注释(是的,类文件生成coulbe通过绑定配置操纵)。我会为自己生成类,看看我能做什么。这对我可以告诉我们很有帮助,您是如何设法使用XJC编译这些模式文件的。 – 2011-12-19 12:36:32

+0

非常感谢,我只是从jaxb开始,我什么都不明白 – Baptiste 2011-12-19 12:39:31

相关问题