オブジェクトに追加したいサブツリーが 1 つあり、JAXB ですべてを単一のツリーとして (適切なタグを使用して) マーシャリングします。ただし、現在、サブツリーのルート タグは別のオブジェクトのタグに置き換えられています。
残念ながら、ここで元のコードを公開することは許可されていないため、テスト コードで問題を再現しました (これがばかげている場合はご容赦ください)。
アイデアは、次の構造を出力したいということです:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:Root xmlns:ns2="urn:my:foo:bar:1.0" xmlns:ns3="urn:other:foo:bar:1.1">
<Content>
<Header>
<ns3:Leaf/>
</Header>
</Content>
</ns2:Root>
しかし、現在、私が得るのはこれだけです:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:Root xmlns:ns2="urn:my:foo:bar:1.0" xmlns:ns3="urn:other:foo:bar:1.1">
<Content>
<Header/>
</Content>
</ns2:Root>
必要なすべてのクラスを生成するために 2 つの XSD があるので、その側では問題ありません (ただし、これらのクラスは生成されるため、変更することはできません)。
2 番目の XML (間違ったもの) を生成するサンプル コードを次に示します。
package foo.bar;
import java.io.OutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class Test {
private JAXBContext context;
public Test() throws JAXBException {
context = JAXBContext.newInstance(RootElement.class, LeafElement.class);
}
@XmlRootElement(name = "Root", namespace = "urn:my:foo:bar:1.0")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Root", propOrder = { "content" })
public static class RootElement {
@XmlElement(name = "Content")
protected ContentElement content;
public ContentElement getContent() {
return content;
}
public void setContent(ContentElement content) {
this.content = content;
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Content", propOrder = { "dummy" })
public static class ContentElement {
@XmlElement(name = "Header")
protected Object dummy;
public Object getDummy() {
return dummy;
}
public void setDummy(Object dummy) {
this.dummy = dummy;
}
}
@XmlRootElement(name = "Leaf", namespace = "urn:other:foo:bar:1.1")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Leaf")
public static class LeafElement {
}
public Node marshal(Object obj) throws JAXBException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = null;
try {
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.newDocument();
} catch (ParserConfigurationException ex) {
throw new JAXBException(ex);
}
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(obj, doc);
return doc.getDocumentElement();
}
public void marshal(Object obj, OutputStream stream) throws JAXBException {
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(obj, stream);
}
public void test() throws JAXBException {
RootElement root = new RootElement();
ContentElement content = new ContentElement();
root.setContent(content);
LeafElement leaf = new LeafElement();
content.setDummy(marshal(leaf));
marshal(root, System.out);
}
public static void main(String[] args) throws JAXBException {
new Test().test();
}
}
そのコードには、3 つの「マーシャリング可能な」クラスがあります。
RootElement
、ContentElement
とLeafElement
.
サンプル コードに示すように、最初の 2 つのクラスは 1 つの XSD (特定の名前空間を持つ) から取得され、最後のクラスは別の XSD (別の名前空間を持つ) から取得されます。
これまでのところ、これを修正するために見つけたdummy
のは、ContentElement のように設定され、それ自体が LeafElement を保持する追加のクラスを作成して、JAXB が適切な中間ノードを作成することだけでした。しかし、私はこの解決策が非常に見苦しく、保守性が低く、JAXB がそのようなケースを処理する何らかの方法を持っていることを望んでいました。
さらに情報が必要な場合、または私の質問を再定式化する必要がある場合は、躊躇しないでください。自分の問題を簡単な言葉で説明するのに苦労しています。
制約は次のとおりです。
- RootElement、ContentElement、または LeafElement を変更できません
- JAXB以外は使えない