如何在字符串中从 XML 加载 org.w3c.dom.Document?

Posted

技术标签:

【中文标题】如何在字符串中从 XML 加载 org.w3c.dom.Document?【英文标题】:How do I load an org.w3c.dom.Document from XML in a string? 【发布时间】:2010-09-07 04:34:04 【问题描述】:

我在字符串中有一个完整的 XML 文档,并且想要一个 Document 对象。谷歌出现了各种各样的垃圾。什么是最简单的解决方案? (在 Java 1.5 中)

解决方案感谢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;

【问题讨论】:

如果您能纠正解决方案,那就太好了。使用 String.getByptes 和 InputStream 会带来 i18n 问题。我的一个朋友从这里得到了代码,这是错误的。幸运的是 findbugs 检测到了这个问题。 erickson 提供的正确解决方案是使用 InputSource。 【参考方案1】:

为了在 Java 中操作 XML,我总是倾向于使用 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();
   

【讨论】:

【参考方案2】:

刚刚遇到了类似的问题,除了我需要一个 NodeList 而不是 Document,这就是我想出的。它与以前的解决方案基本相同,将根元素作为 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;
    

【讨论】:

【参考方案3】:

哇!

此代码可能存在严重问题,因为它忽略了String 中指定的字符编码(默认为 UTF-8)。当您调用 String.getBytes() 时,平台默认编码用于将 Unicode 字符编码为字节。所以,解析器可能认为它正在获取 UTF-8 数据,而实际上它正在获取 EBCDIC 或其他东西……不漂亮!

改为使用带有 InputSource 的 parse 方法,它可以用 Reader 构造,如下所示:

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

这似乎没什么大不了的,但对字符编码问题的无知会导致类似于 y2k 的阴险代码腐烂。

【讨论】:

Google 上的解决方案如此简单但又如此难以捉摸。谢谢+1 我现在意识到,我不应该只是复制并粘贴已接受的答案,而应该通读。 太棒了!通过以下设置在 JDK8 上挽救了我们的生命 file.encoding=ISO-8859_1 , javax.servlet.request.encoding=UTF-8 PS 标记为正确的答案对我们不起作用【参考方案4】:

这在 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()));

【讨论】:

如 sylvarking 的回答中所述,此代码使用 getBytes() 而不考虑编码。 你的意思是埃里克森的回答吗?或者他重命名了他的个人资料? 不应该有演员return (Document) builder.parse(new ByteArrayInputStream(xml.getBytes()));??

以上是关于如何在字符串中从 XML 加载 org.w3c.dom.Document?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中从包含 XML 的字符串中读取数据?

如何在 Java 中从 String 创建 XML 对象?

如何在 Qt 中从 txt 文件中加载大数据

如何在 Maven 中从 pom.xml 调用 testng.xml 文件

如何在 Java 中从 XML 创建 PDF?

如何在 Android 中从 styles.xml 设置 EditText 样式?