Làm cách nào để xuất org.w3c.dom.Element sang định dạng chuỗi trong java?


89

Tôi có một org.w3c.dom.Elementđối tượng được truyền vào phương thức của tôi. Tôi cần xem toàn bộ chuỗi xml bao gồm các nút con của nó (toàn bộ biểu đồ đối tượng). Tôi đang tìm một phương pháp có thể chuyển đổi Elementthành chuỗi định dạng xml mà tôi có thể System.out.printlnsử dụng. Chỉ println()trên đối tượng 'Phần tử' sẽ không hoạt động vì toString()sẽ không xuất ra định dạng xml và sẽ không đi qua nút con của nó. Có cách nào dễ dàng mà không cần viết phương pháp của riêng tôi để làm điều đó không? Cảm ơn.

Câu trả lời:


155

Giả sử bạn muốn gắn bó với API tiêu chuẩn ...

Bạn có thể sử dụng DOMImplementationLS :

Document document = node.getOwnerDocument();
DOMImplementationLS domImplLS = (DOMImplementationLS) document
    .getImplementation();
LSSerializer serializer = domImplLS.createLSSerializer();
String str = serializer.writeToString(node);

Nếu khai báo <? Xml version = "1.0" encoding = "UTF-16"?> Làm phiền bạn, bạn có thể sử dụng một máy biến áp để thay thế:

TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
StringWriter buffer = new StringWriter();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(node),
      new StreamResult(buffer));
String str = buffer.toString();

7
Đây là giải pháp nếu bạn đang nhận được [html: null] và mong đợi HTML. Đã thêm nhận xét này để google có thể lập chỉ mục câu trả lời hy vọng.
Donal Tobin

3
Bạn vẫn có thể sử dụng LSSerializer và xuất "UTF-8". Sử dụng LSOutput với StringWriter thay vào đó và đặt kiểu mã hóa để "UTF- * 8"
ricosrealm

1
Hoạt động với đối tượng Tài liệu w3c
thứ

2
<?xml version="1.0" encoding="UTF-16"?>phiền khai ... chúng tôi cũng có thể thêm dòng này serializer .getDomConfig().setParameter("xml-declaration", false); trong dung dịch đầu tiên ....
Tarsem Singh

cảm ơn câu trả lời của bạn, điều đó thực sự tuyệt vời. Nhưng tôi có một vấn đề với nó, đôi khi một số thẻ của các phần phù hợp bị xóa và nội dung văn bản của chúng chỉ được hiển thị. Bạn có bất kỳ đề xuất cho vấn đề này?
epcpu

16

Mã 4 dòng đơn giản để lấy String mà không cần khai báo xml ( <?xml version="1.0" encoding="UTF-16"?>) từorg.w3c.dom.Element

DOMImplementationLS lsImpl = (DOMImplementationLS)node.getOwnerDocument().getImplementation().getFeature("LS", "3.0");
LSSerializer serializer = lsImpl.createLSSerializer();
serializer.getDomConfig().setParameter("xml-declaration", false); //by default its true, so set it to false to get String without xml-declaration
String str = serializer.writeToString(node);

2

Không được hỗ trợ trong API JAXP tiêu chuẩn, tôi đã sử dụng thư viện JDom cho mục đích này. Nó có chức năng máy in, các tùy chọn định dạng, v.v. http://www.jdom.org/


+1 vì nó không phải là mục đích của API org.w3c.dom tiêu chuẩn. Nếu tôi quan tâm đến các khối XML dưới dạng văn bản, tôi thường chỉ cố gắng phân tích cú pháp nó thành văn bản với kết quả khớp regex (nếu tiêu chí tìm kiếm dễ dàng được biểu diễn dưới dạng regex).
Cornel Masson

2

Nếu bạn có lược đồ của XML hoặc có thể tạo liên kết JAXB cho nó, bạn có thể sử dụng JAXB Marshaller để ghi vào System.out:

import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRootElement
public class BoundClass {

    @XmlAttribute
    private String test;

    @XmlElement
    private int x;

    public BoundClass() {}

    public BoundClass(String test) {
        this.test = test;
    }

    public static void main(String[] args) throws Exception {
        JAXBContext jxbc = JAXBContext.newInstance(BoundClass.class);
        Marshaller marshaller = jxbc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
        marshaller.marshal(new JAXBElement(new QName("root"),BoundClass.class,new Main("test")),System.out);
    }
}

2

Hãy thử jcabi-xml với một lớp lót:

String xml = new XMLDocument(element).toString();

Các phiên bản mới của jcabi-xml không hỗ trợ Element dưới dạng param, chỉ hỗ trợ Node / File / String.
Ermintar

1

đây là những gì được thực hiện trong jcabi:

private String asString(Node node) {
    StringWriter writer = new StringWriter();
    try {
        Transformer trans = TransformerFactory.newInstance().newTransformer();
        // @checkstyle MultipleStringLiterals (1 line)
        trans.setOutputProperty(OutputKeys.INDENT, "yes");
        trans.setOutputProperty(OutputKeys.VERSION, "1.0");
        if (!(node instanceof Document)) {
            trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        }
        trans.transform(new DOMSource(node), new StreamResult(writer));
    } catch (final TransformerConfigurationException ex) {
        throw new IllegalStateException(ex);
    } catch (final TransformerException ex) {
        throw new IllegalArgumentException(ex);
    }
    return writer.toString();
}

và nó hoạt động cho tôi!


0

Với VTD-XML , bạn có thể truyền vào con trỏ và thực hiện một lệnh gọi getElementFragment duy nhất để truy xuất phân đoạn (như được biểu thị bằng độ lệch và độ dài của nó) ... Dưới đây là một ví dụ

import com.ximpleware.*;
public class concatTest{
    public static void main(String s1[]) throws Exception {
        VTDGen vg= new VTDGen();
        String s = "<users><user><firstName>some </firstName><lastName> one</lastName></user></users>";
        vg.setDoc(s.getBytes());
        vg.parse(false);
        VTDNav vn = vg.getNav();
        AutoPilot ap = new AutoPilot(vn);
        ap.selectXPath("/users/user/firstName");
        int i=ap.evalXPath();
        if (i!=1){
            long l= vn.getElementFragment();
            System.out.println(" the segment is "+ vn.toString((int)l,(int)(l>>32)));
        }
    }

}
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.