2008-08-28 3 views
94

У меня есть полный XML-документ в строке, и мне нужен объект Document. Google раскрывает все виды мусора. Какое самое простое решение? (В Java 1.5)Как загрузить org.w3c.dom.Document из XML в строку?

Решение Благодаря Matt McMinn, я остановился на этой реализации. Он имеет правильный уровень гибкости ввода и детализацию исключений для меня. (Это хорошо, чтобы знать, если ошибка пришла от некорректного XML - SAXException - или просто плохо 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

Было бы хорошо, если вы можете исправить решение. Использование String.getByptes и InputStream налагают проблемы i18n. Один из моих друзей получил код отсюда, как это неправильно. К счастью, обнаруженные ошибки обнаружили проблему. Правильным решением, предлагаемым erickson, является использование InputSource. – 2013-08-16 19:46:42

ответ

71

Это работает для меня в Java 1.5 - Я разделся конкретные исключения для удобства чтения.

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

Как отмечено в ответе sylvarking, этот код использует `getBytes()` без учета кодирования. – McDowell 2009-11-24 11:11:51

+2

Вы имеете в виду ответ Эриксона? или, может быть, он переименовал свой профиль? – rogerdpack 2012-12-04 20:57:23

132

Whoa there!

Существует очень серьезная проблема с этим кодом, поскольку он игнорирует кодировку символов, указанную в String (по умолчанию это UTF-8). Когда вы вызываете String.getBytes(), кодировка по умолчанию платформы используется для кодирования символов Unicode в байтах. Таким образом, синтаксический анализатор может подумать, что он получает данные UTF-8, когда на самом деле он получает EBCDIC или что-то в этом роде; не очень!

Вместо этого используйте метод синтаксического анализа, который принимает InputSource, которая может быть построена с помощью чтения, например:

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

Это может показаться не таким большим делом, но незнание вопросов кодирования символов приводит к коварный кодекс, похожий на y2k.

9

У меня была аналогичная проблема, за исключением того, что мне нужен NodeList, а не документ, вот что я придумал. Это в основном такое же решение, как и раньше, расширенное, чтобы получить корневой элемент вниз как NodeList и использовать предложение Эриксона использовать InputSource вместо проблем с кодировкой символов.

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

Чтобы манипулировать XML в Java, я всегда предпочитаю использовать трансформатор 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(); 
} 
Смежные вопросы