在Blaise Doughan 的帮助下,这是我确定的最终解决方案。这包括一些额外的演示代码,以帮助可能遇到这种情况的其他人。
类
ProductList(一个新的包装类,用于展示它如何适用于多个产品条目)
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
@XmlRootElement(name="ProductList")
public class ProductList {
@XmlElementWrapper(name="Products")
@XmlElement(name="Product")
public List<Product> products = new ArrayList<Product>();
}
产品(经过 Blaise 的修改)
import org.w3c.dom.Node;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Product")
@XmlAccessorType(XmlAccessType.FIELD)
public class Product {
@XmlElement(name="CommonProperty")
public String commonProperty="Something";
@XmlAnyElement
public Node extraXml;
}
Main(一些演示代码)
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
public class Main {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// Build some arbitrary extra XML and prepare an InputStream
String fragment1 = "<abc><def>Some extra 1</def></abc>";
String fragment2 = "<ghi><jkl>Some extra 2</jkl></ghi>";
Document document1 = factory.newDocumentBuilder().parse(new InputSource(new StringReader(fragment1)));
Document document2 = factory.newDocumentBuilder().parse(new InputSource(new StringReader(fragment2)));
Product product1 = new Product();
product1.commonProperty = "Hello 1";
product1.extraXml=document1.getFirstChild();
Product product2 = new Product();
product2.commonProperty = "Hello 2";
product2.extraXml=document2.getFirstChild();
ProductList productList = new ProductList();
productList.products.add(product1);
productList.products.add(product2);
JAXBContext jc = JAXBContext.newInstance(ProductList.class, Product.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(productList, System.out);
}
}
最终输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProductList>
<Products>
<Product>
<CommonProperty>Hello 1</CommonProperty>
<abc>
<def>Some extra 1</def>
</abc>
</Product>
<Product>
<CommonProperty>Hello 2</CommonProperty>
<ghi>
<jkl>Some extra 2</jkl>
</ghi>
</Product>
</Products>
</ProductList>
结果!
但它在 JBoss 中不起作用...
如果您在 JBoss 4.2.3.GA 或 4.3 中尝试上述方法,您可能会发现您得到了一个
class com.sun.org.apache.xerces.internal.dom.DocumentFragmentImpl nor any of its super class is known to this context.
报告异常。这(可能)是由于 JBoss lib 和 /lib/endorsed 文件夹中的 xercesImpl.jar 使用 Java META-INF/Services 覆盖工具来防止 JDK 使用内部类进行编组。您可能需要使用以下方法直接指定替代 DocumentBuilderFactory:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance("oracle.xml.jaxp.JXDocumentBuilderFactory", this
.getClass().getClassLoader());
Oracle 实现似乎缓解了这些问题,可能是因为它在 JAXB 上下文中保持对 DOM 节点类的认识。这些类可以在 Oracle 客户端附带的 xdb.jar 和 xmlparserv2.jar 中找到。
希望对你有帮助。