Как вывести 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 Document
третье
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

Не поддерживается в стандартном JAXP API, я использовал для этой цели библиотеку 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);
    }
}
Wierob
источник
2

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

String xml = new XMLDocument(element).toString();
Егор256
источник
Новые версии jcabi-xml не поддерживают Element как параметр, только Node / File / String.
Ermintar
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)));
        }
    }

}
vtd-xml-author
источник