Wie lade ich ein org.w3c.dom.Document aus XML in eine Zeichenfolge?

103

Ich habe ein vollständiges XML-Dokument in einer Zeichenfolge und möchte ein DocumentObjekt. Google taucht alle Arten von Müll auf. Was ist die einfachste Lösung? (In Java 1.5)

Lösung Dank Matt McMinn habe ich mich für diese Implementierung entschieden. Es hat für mich das richtige Maß an Eingabeflexibilität und Ausnahmegranularität. (Es ist gut zu wissen, ob der Fehler von fehlerhaftem XML SAXException- oder nur von schlechten E / A - herrührt 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;
}
Frank Krueger
quelle
Es wäre schön, wenn Sie die Lösung korrigieren können. Die Verwendung von String.getByptes und InputStream führt zu i18n-Problemen. Einer meiner Freunde hat den Code von hier bekommen, wie er falsch ist. Zum Glück haben Findbugs das Problem erkannt. Die richtige Lösung von erickson ist die Verwendung von InputSource.
Kenneth Xu

Antworten:

80

Dies funktioniert für mich in Java 1.5 - ich habe bestimmte Ausnahmen für die Lesbarkeit entfernt.

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()));
}
Matt McMinn
quelle
28
Wie in der Antwort von sylvarking erwähnt, wird dieser Code getBytes()ohne Berücksichtigung der Codierung verwendet.
McDowell
2
meinst du ericksons antwort? oder vielleicht hat er sein Profil umbenannt?
Rogerdpack
1
sollte es nicht Casting geben return (Document) builder.parse(new ByteArrayInputStream(xml.getBytes()));?
InfantPro'Aravind '16.
150

Whoa da!

Es gibt ein potenziell schwerwiegendes Problem mit diesem Code, da er die in String(standardmäßig UTF-8) angegebene Zeichencodierung ignoriert . Wenn du anrufstString.getBytes() die Plattform die Standardcodierung verwendet, um Unicode-Zeichen in Bytes zu codieren. Der Parser könnte also denken, dass er UTF-8-Daten erhält, obwohl er tatsächlich EBCDIC oder etwas anderes erhält… nicht schön!

Verwenden Sie stattdessen die Analysemethode, die eine InputSource verwendet, die mit einem Reader wie folgt erstellt werden kann:

import java.io.StringReader;
import org.xml.sax.InputSource;

        return builder.parse(new InputSource(new StringReader(xml)));

Es scheint keine große Sache zu sein, aber die Unkenntnis der Probleme bei der Zeichenkodierung führt zu heimtückischem Code, der dem Jahr 2000 ähnelt.

erickson
quelle
3
So einfach, aber so schwer fassbar eine Lösung bei Google. Vielen Dank +1
pat8719
6
Mir ist jetzt klar, dass ich die akzeptierte Antwort nicht nur kopieren und einfügen, sondern durchlesen sollte.
Vitaly Sazanovich
1
Genial! Rettete unser Leben auf JDK8 mit der folgenden Setup-Datei.encoding = ISO-8859_1, javax.servlet.request.encoding = UTF-8 PS Die als korrekt gekennzeichnete Antwort hat bei uns nicht
funktioniert
9

Hatte gerade 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 Stammelement als NodeList zu speichern 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;
    }
shsteimer
quelle
1

Um XML in Java zu manipulieren, verwende ich immer die Transformer-API:

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