Як завантажувати org.w3c.dom.Document з XML у рядок?


103

У мене є повний XML-документ у рядку і хотів би Documentоб’єкт. Google виявляє всіляке сміття. Яке найпростіше рішення? (На Java 1.5)

Рішення Завдяки Метту Макмінну я зупинився на цій реалізації. Для мене потрібний рівень гнучкості введення та деталізація виключень. (Добре знати, чи помилка виникла із неправильно сформованого 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;
}

Було б добре, якщо ви зможете виправити рішення. Використання String.getByptes та InputStream нав'язують проблеми i18n. Один мій друг отримав код звідси, як це неправильно. Пощастило, що проблему виявили проблеми. Правильне рішення, яке надає erickson, - це використовувати InputSource.
Кеннет Сю

Відповіді:


80

Це працює для мене в 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()));
}

28
Як зазначається у відповіді sylvarking, цей код використовується getBytes()без врахування для кодування.
Макдауелл

2
ти маєш на увазі відповідь еріксона? а може він перейменував свій профіль?
rogerdpack

1
не повинно бути кастинг return (Document) builder.parse(new ByteArrayInputStream(xml.getBytes()));??
InfantPro'Aravind '16

150

Що там!

Існує потенційно серйозна проблема з цим кодом, оскільки він ігнорує кодування символів, вказане в String(який за замовчуванням є UTF-8). При виклику String.getBytes()платформи за замовчуванням кодування використовується для кодування символів Unicode в байти. Отже, аналізатор може подумати, що він отримує дані UTF-8, коли насправді він отримує EBCDIC чи щось таке ... не дуже!

Натомість використовуйте метод розбору, який бере InputSource, який можна сконструювати за допомогою Reader, наприклад:

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

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

Це може не здатися великою справою, але незнання питань кодування символів призводить до підступного коду, гнилого схожого на y2k.


3
Настільки просте, але таке невловиме рішення в Google. Дякую +1
pat8719

6
Зараз я усвідомлюю, що я не повинен просто скопіювати та вставити прийняту відповідь, а скоріше прочитати її.
Віталій Сазанович

1
Дивовижно! Врятували наше життя на JDK8 з наступним налаштуванням file.encoding = ISO-8859_1, javax.servlet.request.encoding = UTF-8 PS відповідь, позначена як правильна, не працювала для нас
kosta5

9

Просто у мене була подібна проблема, за винятком того, що мені потрібен NodeList, а не документ, ось що я придумав. Це, головним чином, те саме рішення, що і раніше, доповнене, щоб знизити кореневий елемент як NodeList і використовувати пропозицію erickson використовувати 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 Transformer:

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();
}   
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.