Bagaimana cara saya menampilkan org.w3c.dom.Element ke format string di java?

90

Saya memiliki org.w3c.dom.Elementobjek yang dimasukkan ke dalam metode saya. Saya perlu melihat seluruh string xml termasuk node anaknya (seluruh grafik objek). Saya mencari metode yang dapat mengubah Elementmenjadi string format xml yang saya bisa System.out.println. Hanya println()pada objek 'Elemen' tidak akan berfungsi karena toString()tidak akan menampilkan format xml dan tidak akan melalui simpul anaknya. Apakah ada cara mudah tanpa menulis metode saya sendiri untuk melakukan itu? Terima kasih.

Doug Porter
sumber

Jawaban:

155

Dengan asumsi Anda ingin tetap menggunakan API standar ...

Anda bisa menggunakan DOMImplementationLS :

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

Jika deklarasi <? Xml version = "1.0" encoding = "UTF-16"?> Mengganggu Anda, Anda dapat menggunakan transformator sebagai gantinya:

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();
McDowell
sumber
7
Ini adalah solusi jika Anda mendapatkan [html: null] dan mengharapkan HTML. Menambahkan komentar ini sehingga google dapat mengindeks jawabannya dengan mudah.
Donal Tobin
3
Anda masih dapat menggunakan LSSerializer dan keluaran "UTF-8". Gunakan LSOutput dengan StringWriter sebagai gantinya dan setel jenis pengkodean ke "UTF- * 8"
ricosrealm
1
Bekerja dengan objek Dokumen w3c juga
ketiga
2
<?xml version="1.0" encoding="UTF-16"?>deklarasi mengganggu ... kita juga dapat menambahkan baris ini serializer .getDomConfig().setParameter("xml-declaration", false); di solusi pertama ....
Tarsem Singh
terima kasih atas jawaban Anda, itu sangat bagus. Tapi saya punya masalah dengan itu, terkadang beberapa tag dari bagian yang cocok dihapus dan konten teksnya hanya ditampilkan. Apakah Anda punya saran untuk masalah ini?
epcpu
16

Kode 4 baris sederhana untuk didapatkan String tanpa xml-declaration ( <?xml version="1.0" encoding="UTF-16"?>) dariorg.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);
Tarsem Singh
sumber
2

Tidak didukung dalam JAXP API standar, saya menggunakan perpustakaan JDom untuk tujuan ini. Ini memiliki fungsi printer, opsi formatter dll. Http://www.jdom.org/

Karl
sumber
+1 untuk itu bukan maksud dari API org.w3c.dom standar. Jika saya tertarik dengan blok XML sebagai teks, saya biasanya hanya mencoba menguraikannya sebagai teks dengan pencocokan ekspresi reguler (jika kriteria pencarian mudah direpresentasikan sebagai ekspresi reguler).
Cornel Masson
2

Jika Anda memiliki skema XML atau sebaliknya dapat membuat JAXB binding untuknya, Anda dapat menggunakan JAXB Marshaller untuk menulis ke 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);
    }
}
wierob
sumber
2

Coba jcabi-xml dengan satu liner:

String xml = new XMLDocument(element).toString();
yegor256
sumber
Versi baru jcabi-xml tidak mendukung Element sebagai param, hanya Node / File / String.
Ermintar
1

inilah yang dilakukan di 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();
}

dan itu berhasil untuk saya!

petir
sumber
0

Dengan VTD-XML , Anda dapat meneruskan ke kursor dan membuat satu panggilan getElementFragment untuk mengambil segmen (sebagaimana dilambangkan dengan offset dan panjangnya) ... Di bawah ini adalah contohnya

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)));
        }
    }

}
vtd-xml-author
sumber