Як вивести org.w3c.dom.Element у формат рядка в Java?


89

У мене є метод, org.w3c.dom.Elementпереданий у мій метод. Мені потрібно побачити весь рядок xml, включаючи його дочірні вузли (весь графік об’єкта). Я шукаю метод, який може перетворити Elementна рядок формату xml, який я можу System.out.println. Просто println()об’єкт «Елемент» не працюватиме, оскільки toString()не виводить формат xml і не проходить через його дочірній вузол. Чи є простий спосіб без написання власного методу це зробити? Дякую.

Відповіді:


155

Якщо припустити, що ви хочете дотримуватися стандартного API ...

Ви можете використовувати DOMImplementationLS :

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

Якщо декларація <? Xml version = "1.0" encoding = "UTF-16"?> Вас турбує, замість цього ви можете використати трансформатор :

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
Це рішення, якщо ви отримуєте [html: null] і очікуєте HTML. Додав цей коментар, щоб Google міг сподіватися на індексацію відповіді.
Донал Тобін

3
Ви все ще можете використовувати LSSerializer і вивести "UTF-8". Замість цього використовуйте LSOutput із StringWriter і встановіть тип кодування на "UTF- * 8"
ricosrealm

1
Працює і з об'єктом документа w3c
третій

2
<?xml version="1.0" encoding="UTF-16"?>декларація турбує ... ми також можемо додати цей рядок serializer .getDomConfig().setParameter("xml-declaration", false); у перше рішення ....
Тарсем Сінгх

дякую за вашу відповідь, це справді чудово. Але у мене з цим проблема, іноді деякі теги відповідних частин видаляються, а текстовий вміст відображається виключно. Чи є у вас пропозиції щодо цієї проблеми?
epcpu

16

Простий 4-рядковий код, який можна отримати String без xml-декларації ( <?xml version="1.0" encoding="UTF-16"?>) з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

Не підтримується стандартним API JAXP, для цього я використовував бібліотеку JDom. Він має функцію принтера, параметри форматування тощо. Http://www.jdom.org/


+1, оскільки це не є наміром стандартного API org.w3c.dom. Якщо мене цікавлять блоки XML як текст, я зазвичай просто намагаюся розібрати його як текст із відповідністю регулярного виразу (якщо критерії пошуку легко представити як регулярний вираз).
Корнел Массон,

2

Якщо у вас є схема XML або ви можете іншим чином створити для неї прив'язки JAXB, ви можете скористатися JAXB Marshaller для запису в 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

Спробуйте jcabi-xml з одним вкладишем:

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

Нові версії jcabi-xml не підтримують Element як параметр, лише Node / File / String.
Ермінтар

1

це те, що зроблено в 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();
}

і це працює для мене!


0

За допомогою VTD-XML ви можете перейти в курсор і зробити один виклик getElementFragment для отримання сегмента (як позначено його зміщенням та довжиною) ... Нижче наведено приклад

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

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.