2008-08-28 9 views
94

Mam kompletny dokument XML w ciągu znaków i chciałbym obiektu Document. Google wyszukuje różnego rodzaju śmieci. Jakie jest najprostsze rozwiązanie? (W Javie 1.5)Jak załadować plik org.w3c.dom.Document z XML w ciągu znaków?

Rozwiązanie Dzięki Matt McMinn, zdecydowałem się na tę realizację. Ma odpowiedni poziom elastyczności wejściowej i wyjątkowej ziarnistości dla mnie. (Dobrze jest wiedzieć, czy błąd pochodzi od zniekształconego XML - SAXException - lub po prostu złe 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

Byłoby miło, gdyby można skorygować rozwiązanie. Używanie String.getByptes i InputStream narzucają problemy i18n. Jeden z moich znajomych dostał kod z tego, co jest złe. Na szczęście to odkrywcy wykryli problem. Prawidłowym rozwiązaniem dostarczonym przez erickson jest użycie InputSource. –

Odpowiedz

71

To działa na mnie w Java 1.5 - rozebrałem konkretne wyjątki dla czytelności.

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

Jak zauważono w odpowiedzi sylvarking, ten kod używa 'getBytes()' bez uwzględniania kodowania. – McDowell

+2

masz na myśli odpowiedź ericksona? czy może zmienił nazwę swojego profilu? – rogerdpack

+1

nie powinno być rzutowania 'return (Document) builder.parse (new ByteArrayInputStream (xml.getBytes()));' ?? –

132

Whoa there!

Istnieje poważny problem z tym kodem, ponieważ ignoruje kodowanie znaków określone w String (co jest domyślnie UTF-8). Po wywołaniu String.getBytes() kodowanie domyślne platformy służy do kodowania znaków Unicode do bajtów. Tak więc parser może myśleć, że pobiera dane z UTF-8, gdy w rzeczywistości dostaje EBCDIC lub coś i hellip; nie ładne!

Zamiast tego należy użyć metody parse że bierze InputSource, które mogą być wykonane z czytnika tak:

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

Nie może wydawać się nic wielkiego, ale nieznajomość zagadnień kodowania znaków prowadzi do podstępny kod zgnilizny podobny do y2k.

+3

Proste, ale nieuchwytne rozwiązanie w Google. Dziękuję +1 – pat8719

+5

Zdaję sobie teraz sprawę, że nie powinienem kopiować i wklejać zaakceptowanej odpowiedzi, ale raczej przeczytać. –

+1

Awesome! Uratował nam życie w JDK8 dzięki następującym plikom instalacyjnym file.encoding = ISO-8859_1, javax.servlet.request.encoding = UTF-8 PS odpowiedź oznaczona jako poprawna nie działała dla nas – kosta5

9

Po prostu miałem podobny problem, z wyjątkiem tego, że potrzebowałem NodeListy, a nie dokumentu, oto co wymyśliłem. Jest to w większości to samo rozwiązanie, co poprzednio, powiększone, aby uzyskać element główny jako NodeList i korzystając z sugestii Ericksona o użyciu InputSource zamiast problemów z kodowaniem znaków.

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

Aby manipulować XML w Javie, zawsze mają tendencję do korzystania z API Transformers:

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(); 
} 
Powiązane problemy