2008-08-28 14 views
94

Ich habe ein komplettes XML-Dokument in einer Zeichenfolge und möchte ein Document Objekt. Google deckt alle Arten von Müll auf. Was ist die einfachste Lösung? (In Java 1.5)Wie lade ich ein org.w3c.dom.Document aus XML in einer Zeichenfolge?

Lösung Dank Matt McMinn habe ich mich auf diese Implementierung festgelegt. Es hat das richtige Maß an Input-Flexibilität und Exception-Granularität für mich. (Es ist gut zu wissen, ob der Fehler von fehlerhaften XML kam - SAXException - oder nur schlecht IO - IOException.)

public static org.w3c.dom.Document loadXMLFrom(String xml) 
    throws org.xml.sax.SAXException, java.io.IOException { 
    return loadXMLFrom(new java.io.ByteArrayInputStream(xml.getBytes())); 
} 

public static org.w3c.dom.Document loadXMLFrom(java.io.InputStream is) 
    throws org.xml.sax.SAXException, java.io.IOException { 
    javax.xml.parsers.DocumentBuilderFactory factory = 
     javax.xml.parsers.DocumentBuilderFactory.newInstance(); 
    factory.setNamespaceAware(true); 
    javax.xml.parsers.DocumentBuilder builder = null; 
    try { 
     builder = factory.newDocumentBuilder(); 
    } 
    catch (javax.xml.parsers.ParserConfigurationException ex) { 
    } 
    org.w3c.dom.Document doc = builder.parse(is); 
    is.close(); 
    return doc; 
} 
+0

Es wäre schön, wenn Sie die Lösung korrigieren. Die Verwendung von String.getByptes und InputStream führt zu Problemen mit i18n. Einer meiner Freunde hat den Code von hier bekommen, was falsch ist. Glücklich, dass Findbugs das Problem entdeckt haben. Die richtige Lösung von Erickson ist die Verwendung von InputSource. –

Antwort

71

Dies funktioniert für mich in Java 1.5 - ich bestimmte Ausnahmen aus Gründen der Lesbarkeit abgezogen.

import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.DocumentBuilder; 
import org.w3c.dom.Document; 
import java.io.ByteArrayInputStream; 

public Document loadXMLFromString(String xml) throws Exception 
{ 
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 

    factory.setNamespaceAware(true); 
    DocumentBuilder builder = factory.newDocumentBuilder(); 

    return builder.parse(new ByteArrayInputStream(xml.getBytes())); 
} 
+27

Wie in der Antwort von sylvarking angemerkt, verwendet dieser Code 'getBytes()' ohne Berücksichtigung der Kodierung. – McDowell

+2

meinst du ericksons antwort? oder vielleicht hat er sein Profil umbenannt? – rogerdpack

+1

sollte nicht gegossen werden 'return (Document) builder.parse (neues ByteArrayInputStream (xml.getBytes()));' ?? –

132

Whoa da!

Es gibt ein potentiell schwerwiegendes Problem mit diesem Code, da er die in String angegebene Zeichencodierung ignoriert (standardmäßig UTF-8). Wenn Sie String.getBytes() aufrufen, wird die Plattformstandardcodierung zum Codieren von Unicode-Zeichen in Byte verwendet. Also könnte der Parser denken, dass er UTF-8-Daten bekommt, wenn er tatsächlich EBCDIC oder etwas & hellip bekommt; nicht hübsch!

Verwenden Sie stattdessen die Parse-Methode, die eine Input nimmt, die mit einem Reader konstruiert werden kann, wie folgt aus:

import java.io.StringReader; 
import org.xml.sax.InputSource; 
… 
     return builder.parse(new InputSource(new StringReader(xml))); 

Es kann nicht wie eine große Sache sein, aber Unkenntnis der Zeichencodierung Fragen führt zu heimtückischer Code rot ähnlich wie y2k.

+3

So einfach, aber so schwer eine Lösung auf Google. Danke +1 – pat8719

+5

Ich merke jetzt, dass ich nicht einfach die angenommene Antwort kopieren und einfügen, sondern durchlesen soll. –

+1

Super! Gespeichert unsere Leben auf JDK8 mit folgendem Setup file.encoding = ISO-8859_1, javax.servlet.request.encoding = UTF-8 PS die als richtig bezeichnete Antwort funktionierte nicht für uns – kosta5

9

hatte nur ein ähnliches Problem, außer dass ich eine NodeList und kein Dokument brauchte, hier ist, was ich mir ausgedacht habe. Es ist größtenteils die gleiche Lösung wie zuvor, erweitert, um das root-Element als NodeList herunterzufahren und den Vorschlag von Erickson zu verwenden, stattdessen eine InputSource für Zeichencodierungsprobleme zu verwenden.

private String DOC_ROOT="root"; 
String xml=getXmlString(); 
Document xmlDoc=loadXMLFrom(xml); 
Element template=xmlDoc.getDocumentElement(); 
NodeList nodes=xmlDoc.getElementsByTagName(DOC_ROOT); 

public static Document loadXMLFrom(String xml) throws Exception { 
     InputSource is= new InputSource(new StringReader(xml)); 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     factory.setNamespaceAware(true); 
     DocumentBuilder builder = null; 
     builder = factory.newDocumentBuilder(); 
     Document doc = builder.parse(is); 
     return doc; 
    } 
1

Um XML in Java, zu manipulieren Ich neige dazu, immer den Transformator-API zu verwenden:

import javax.xml.transform.Source; 
import javax.xml.transform.TransformerException; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.dom.DOMResult; 
import javax.xml.transform.stream.StreamSource; 

public static Document loadXMLFrom(String xml) throws TransformerException { 
    Source source = new StreamSource(new StringReader(xml)); 
    DOMResult result = new DOMResult(); 
    TransformerFactory.newInstance().newTransformer().transform(source , result); 
    return (Document) result.getNode(); 
} 
Verwandte Themen