Làm cách nào để tải org.w3c.dom.Document từ XML trong một chuỗi?


103

Tôi có một tài liệu XML hoàn chỉnh trong một chuỗi và muốn có một Documentđối tượng. Google tìm ra tất cả các loại rác. Giải pháp đơn giản nhất là gì? (Trong Java 1.5)

Giải pháp Cảm ơn Matt McMinn , tôi đã giải quyết việc triển khai này. Nó có mức độ linh hoạt đầu vào và độ chi tiết ngoại lệ phù hợp với tôi. (Thật tốt nếu biết lỗi đến từ XML không đúng định dạng - SAXException- hay chỉ là IO xấu - 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;
}

Sẽ rất tốt nếu bạn có thể sửa giải pháp. Sử dụng String.getByptes và InputStream áp đặt các vấn đề của i18n. Một trong những người bạn của tôi đã nhận được mã từ đây như là sai. May mắn thay, những con bọ tìm thấy sự cố. Giải pháp chính xác được cung cấp bởi erickson là sử dụng InputSource.
Kenneth Xu

Câu trả lời:


80

Điều này phù hợp với tôi trong Java 1.5 - Tôi đã loại bỏ các ngoại lệ cụ thể để dễ đọc.

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
Như đã lưu ý trong câu trả lời của sylvarking, mã này getBytes()không được sử dụng để mã hóa.
McDowell

2
ý bạn là câu trả lời của erickson? hoặc có thể anh ấy đã đổi tên hồ sơ của mình?
rogerdpack

1
không nên casting return (Document) builder.parse(new ByteArrayInputStream(xml.getBytes()));??
InfantPro'Aravind '

150

Họ đấy!

Có một sự cố nghiêm trọng tiềm ẩn với mã này, vì nó bỏ qua mã hóa ký tự được chỉ định trong String(theo mặc định là UTF-8). Khi bạn gọi String.getBytes(), mã hóa mặc định của nền tảng được sử dụng để mã hóa các ký tự Unicode thành byte. Vì vậy, trình phân tích cú pháp có thể nghĩ rằng nó đang nhận dữ liệu UTF-8 trong khi thực tế nó đang nhận EBCDIC hoặc một cái gì đó… không đẹp!

Thay vào đó, hãy sử dụng phương pháp phân tích cú pháp lấy InputSource, có thể được xây dựng bằng Reader, như sau:

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

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

Nó có vẻ không phải là một vấn đề lớn, nhưng sự thiếu hiểu biết về các vấn đề mã hóa ký tự dẫn đến việc thối mã ngấm ngầm tương tự như y2k.


3
Rất đơn giản nhưng rất khó nắm bắt một giải pháp trên Google. Cảm ơn bạn +1
pat8719

6
Bây giờ tôi nhận ra rằng tôi không nên chỉ sao chép và dán câu trả lời được chấp nhận mà nên đọc qua.
Vitaly Sazanovich

1
Tuyệt vời! Cứu mạng chúng tôi trên JDK8 với sau thiết lập file.encoding = ISO-8859_1, javax.servlet.request.encoding = UTF-8 PS câu trả lời dán nhãn là didnt làm việc đúng đối với chúng tôi
kosta5

9

Vừa gặp sự cố tương tự, ngoại trừ việc tôi cần NodeList chứ không phải Tài liệu, đây là những gì tôi đã nghĩ ra. Nó chủ yếu là giải pháp giống như trước đây, được tăng cường để lấy phần tử gốc xuống dưới dạng NodeList và sử dụng gợi ý của erickson về việc sử dụng InputSource thay thế cho các vấn đề mã hóa ký tự.

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

Để thao tác với XML trong Java, tôi luôn có xu hướng sử dụng 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();
}   
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.