Jak wyprowadzić element org.w3c.dom.Element do formatu ciągu w java?

89

Mam org.w3c.dom.Elementobiekt przekazany do mojej metody. Muszę zobaczyć cały ciąg XML, w tym jego węzły podrzędne (cały wykres obiektu). Szukam metody, która może przekonwertować Elementna ciąg formatu xml, który mogę System.out.printlnna. Po prostu obiekt println()„Element” nie zadziała, ponieważ toString()nie wyprowadzi formatu xml i nie przejdzie przez węzeł podrzędny. Czy istnieje łatwy sposób na zrobienie tego bez pisania własnej metody? Dzięki.

Doug Porter
źródło

Odpowiedzi:

155

Zakładając, że chcesz trzymać się standardowego interfejsu API ...

Możesz użyć DOMImplementationLS :

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

Jeśli przeszkadza Ci deklaracja <? Xml version = "1.0" encoding = "UTF-16"?>, Możesz zamiast tego użyć transformatora :

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
źródło
7
To jest rozwiązanie, jeśli otrzymujesz [html: null] i oczekujesz kodu HTML. Dodałem ten komentarz, aby Google mógł zindeksować odpowiedź, miejmy nadzieję.
Donal Tobin
3
Nadal możesz używać LSSerializera i wyświetlać „UTF-8”. Zamiast tego użyj LSOutput z StringWriter i ustaw typ kodowania na „UTF- * 8”
ricosrealm
1
Działa również z obiektem dokumentu w3c
trzydziestego
2
<?xml version="1.0" encoding="UTF-16"?>deklaracja przeszkadza ... możemy też dodać tę linię serializer .getDomConfig().setParameter("xml-declaration", false); w pierwszym rozwiązaniu ....
Tarsem Singh
dziękuję za odpowiedź, to świetnie. Ale mam z tym problem, czasami niektóre tagi z dopasowanych części są usuwane, a ich treść jest wyświetlana wyłącznie. Czy masz jakieś sugestie dotyczące tego problemu?
epcpu
16

Prosty czterowierszowy kod do pobrania String bez deklaracji xml ( <?xml version="1.0" encoding="UTF-16"?>) zorg.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
źródło
2

Nieobsługiwany w standardowym JAXP API, wykorzystałem do tego bibliotekę JDom. Posiada funkcję drukarki, opcje formatyzatora itp. Http://www.jdom.org/

Karl
źródło
+1 za to, że nie jest to intencją standardowego interfejsu API org.w3c.dom. Jeśli interesują mnie bloki XML jako tekst, zwykle próbuję po prostu przeanalizować go jako tekst z dopasowaniem wyrażenia regularnego (jeśli kryteria wyszukiwania można łatwo przedstawić jako wyrażenie regularne).
Cornel Masson
2

Jeśli masz schemat XML lub możesz w inny sposób utworzyć dla niego powiązania JAXB, możesz użyć JAXB Marshaller, aby napisać do 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
źródło
2

Wypróbuj jcabi-xml z jedną linijką :

String xml = new XMLDocument(element).toString();
yegor256
źródło
Nowe wersje jcabi-xml nie obsługują elementu jako parametru, tylko Node / File / String.
Ermintar
1

oto, co robi się w 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();
}

i to działa dla mnie!

thunderhawk
źródło
0

Dzięki VTD-XML możesz przejść do kursora i wykonać pojedyncze wywołanie getElementFragment w celu pobrania segmentu (zgodnie z jego przesunięciem i długością) ... Poniżej znajduje się przykład

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
źródło