XML에서 문자열로 org.w3c.dom.Document를로드하려면 어떻게해야합니까?


103

문자열에 완전한 XML 문서가 있고 Document객체를 원합니다 . Google은 모든 종류의 쓰레기를 찾아냅니다. 가장 간단한 해결책은 무엇입니까? (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를 사용하는 것입니다.
Kenneth Xu

답변:


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()인코딩을 고려하지 않고 사용합니다 .
McDowell

2
erickson의 대답을 의미합니까? 아니면 프로필 이름을 바꿨 을까요?
rogerdpack 2012

1
캐스팅이 return (Document) builder.parse(new ByteArrayInputStream(xml.getBytes()));안되나 ??
InfantPro'Aravind '2013 년

150

우와!

이 코드에는에 지정된 문자 인코딩 String(기본적으로 UTF-8)을 무시하기 때문에 잠재적으로 심각한 문제가 있습니다. String.getBytes()플랫폼 을 호출 하면 유니 코드 문자를 바이트로 인코딩하는 데 기본 인코딩이 사용됩니다. 따라서 파서는 실제로 EBCDIC 등을 받고있을 때 UTF-8 데이터를 받고 있다고 생각할 수 있습니다. 예쁘지 않습니다!

대신 다음과 같이 Reader로 구성 할 수있는 InputSource를 사용하는 구문 분석 메서드를 사용합니다.

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

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

큰 문제처럼 보이지는 않지만 문자 인코딩 문제를 모르면 y2k와 유사한 교활한 코드 부패가 발생합니다.


3
너무 간단하지만 Google에서 찾기 어려운 솔루션입니다. 감사합니다 +1
pat8719 2012

6
이제 받아 들여진 답을 복사해서 붙여 넣는 것이 아니라 읽어야한다는 것을 이제 깨달았습니다.
Vitaly Sazanovich 2013

1
대박! 설정하여 file.encoding = 다음과 JDK8에 우리의 삶에 저장된 ISO-8859_1, javax.servlet.request.encoding = UTF-8 PS 올바른 didnt가 된 우리를 위해 작업으로 분류 대답
kosta5

9

문서가 아닌 NodeList가 필요하다는 점을 제외하면 비슷한 문제가 발생했습니다. 여기에 제가 생각해 낸 것이 있습니다. 루트 요소를 NodeList로 가져오고 문자 인코딩 문제 대신 InputSource를 사용하라는 erickson의 제안을 사용하여 이전과 거의 동일한 솔루션입니다.

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

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();
}   
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.