2013-06-13 3 views
11

Das gibt mir ein Dokument-Objekt mit einem Top-Level-Knoten ohne Kindknoten:wie ein JAXB-Objekt zu org.w3c.dom.Document marshalieren?

public static Document getDocument(Object jaxb) 
{ 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    //dbf.setNamespaceAware(true); 
    Document doc = dbf.newDocumentBuilder().newDocument(); 

    JAXBContext context = JAXBContext.newInstance(jaxb.getClass()); 
    context.createMarshaller().marshal(jaxb, doc); 

    return doc; 
} 

Dies ist die Abhilfe, die noch ineffizient scheint, da es zu String konvertiert und dann auf dem Dokument.

public static Document getDocument(Object jaxb) 
{       
    StringWriter writer = new StringWriter();  
    JAXBContext context = JAXBContext.newInstance(jaxb.getClass()); 
    context.createMarshaller().marshal(jaxb, writer); 

    return DocumentBuilderFactory.newInstance().newDocumentBuilder(). 
parse(new InputSource(new StringReader(writer.toString())); 
} 

Ist es möglich zu erreichen, was ich versuche zu erreichen?

+0

Es stellte sich heraus, dass das Problem nicht von JAXB zu dokumentieren. Das Problem bestand darin, dass Namespace-agnostische XPath-Abfragen aus irgendeinem Grund nicht mit dem Document-Objekt funktionieren, das von der ersten Methode zurückgegeben wurde, sondern mit dem Document-Objekt funktionieren, das von der zweiten Methode zurückgegeben wurde. Die Lösung - zumindest für jetzt - besteht darin, meine Xpath-Abfragen neu zu schreiben. –

+0

Als späte Anmerkung: Der Grund, warum Namespace-Agnostic XPath-Abfragen funktionieren, wenn Sie Ihre gemarshallt Daten analysieren, liegt daran, dass Dokument-Builder standardmäßig kein Namespace kennen. Wenn JAXB das DOM erstellt, sind die DocumentBuilder-Einstellungen nicht relevant, da kein Parsing beteiligt ist. – Michael

Antwort

13

Was Sie arbeiten tun sollten. Hier ein Beispiel:

Domain Model (Foo)

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Foo { 

    private String bar; 

    public String getBar() { 
     return bar; 
    } 

    public void setBar(String bar) { 
     this.bar = bar; 
    } 

} 

Demo

import javax.xml.bind.*; 
import javax.xml.parsers.*; 
import javax.xml.transform.*; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 

import org.w3c.dom.Document; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     // Create the JAXBContext 
     JAXBContext jc = JAXBContext.newInstance(Foo.class); 

     // Create the Object 
     Foo foo = new Foo(); 
     foo.setBar("Hello World"); 

     // Create the Document 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     Document document = db.newDocument(); 

     // Marshal the Object to a Document 
     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.marshal(foo, document); 

     // Output the Document 
     TransformerFactory tf = TransformerFactory.newInstance(); 
     Transformer t = tf.newTransformer(); 
     DOMSource source = new DOMSource(document); 
     StreamResult result = new StreamResult(System.out); 
     t.transform(source, result); 
    } 

} 

Ausgabe

<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>Hello World</bar></foo> 
+0

Versuchen Sie, Ihrem XML-Beispieldokument einen Namespace hinzuzufügen und das Dokument dann mit einem Xpath-Ausdruck abzufragen, der Namespaces nicht berücksichtigt. Zum Beispiel: // foo/bar im Vergleich zu // ns: foo/ns: bar –

+1

@JSmith - Wenn das Dokument dem Namespace entspricht, sollten Sie den XPath-Namespace darauf aufmerksam machen. Die Tatsache, dass Sie beim Marshalling auf 'DOMsource' gegenüber' Document' ein anderes Verhalten sehen, ist ein Beweis dafür. Wenn Sie Parser oder JAXB-Provider vertauscht haben, würden Sie wahrscheinlich andere Ergebnisse sehen. –

11

versuchen diese

DOMResult res = new DOMResult(); 
    JAXBContext context = JAXBContext.newInstance(obj.getClass()); 
    context.createMarshaller().marshal(obj, res); 
    Document doc = (Document) res.getNode(); 
+0

Es stellte sich heraus, dass das Problem nicht von JAXB zum Dokumentieren Marshalling war. Das Problem bestand darin, dass Namespace-agnostische XPath-Abfragen aus irgendeinem Grund nicht mit dem Document-Objekt funktionieren, das von der ersten Methode zurückgegeben wurde, sondern mit dem Document-Objekt funktionieren, das von der zweiten Methode zurückgegeben wurde. Die Lösung - zumindest für jetzt - besteht darin, meine Xpath-Abfragen neu zu schreiben. –