2013-06-13 14 views
11

questo mi dà un oggetto Document con un nodo di primo livello senza nodi figli:come eseguire il marshalling di un oggetto JAXB su org.w3c.dom.Document?

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

Questa è la soluzione, che sembra ancora più inefficiente, dal momento che converte in stringa e poi al documento.

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

È possibile realizzare ciò che sto cercando di realizzare?

+0

scopre che il problema era non eseguire il marshalling da JAXB per documentare. Il problema era che, per qualche ragione, le query XPath agnostiche dei namespace non funzionano con l'oggetto Document restituito dal primo metodo, ma funzionano bene con l'oggetto Document restituito dal secondo metodo. La soluzione - almeno per ora - è di riscrivere le mie query Xpath. –

+0

Come commento in ritardo: il motivo per cui le query XPath agnostiche dei namespace funzionano se si analizzano i dati sottoposti a marshalling perché i builder di documenti non sono per impostazione predefinita sullo spazio dei nomi. Quando JAXB crea il DOM, le impostazioni di DocumentBuilder non sono rilevanti perché non sono coinvolte le analisi. – Michael

risposta

13

Quello che state facendo dovrebbe funzionare. Ecco un esempio:

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

} 

uscita

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

Provare ad aggiungere uno spazio dei nomi al documento XML di esempio e quindi eseguire una query del documento utilizzando un'espressione Xpath che non tenga conto degli spazi dei nomi. Ad esempio: // foo/bar contro // ns: foo/ns: bar –

+1

@JSmith - Il documento è sensibile allo spazio dei nomi, quindi è necessario rendere lo spazio dei nomi XPath consapevole. Il fatto che si osservi un comportamento diverso quando si esegue il marshalling su 'DOMSource' rispetto a' Document' ne è la prova. Se scambiate parser o provider JAXB, probabilmente vedrete risultati diversi. –

11

provare questo

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

Si scopre che il problema non era il marshalling da JAXB al documento. Il problema era che, per qualche ragione, le query XPath agnostiche dei namespace non funzionano con l'oggetto Document restituito dal primo metodo, ma funzionano bene con l'oggetto Document restituito dal secondo metodo. La soluzione - almeno per ora - è di riscrivere le mie query Xpath. –

Problemi correlati