Comment sortir org.w3c.dom.Element au format chaîne en Java?


89

J'ai un org.w3c.dom.Elementobjet passé dans ma méthode. J'ai besoin de voir toute la chaîne xml, y compris ses nœuds enfants (le graphique d'objet entier). Je recherche une méthode qui peut convertir le Elementen une chaîne de format xml sur laquelle je peux System.out.println. Juste println()sur l'objet 'Element' ne fonctionnera pas car toString()il ne produira pas le format xml et ne passera pas par son nœud enfant. Y a-t-il un moyen facile sans écrire ma propre méthode pour le faire? Merci.

Réponses:


155

En supposant que vous souhaitiez vous en tenir à l'API standard ...

Vous pouvez utiliser un DOMImplementationLS :

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

Si la déclaration <? Xml version = "1.0" encoding = "UTF-16"?> Vous dérange, vous pouvez utiliser un transformateur à la place:

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
C'est la solution si vous obtenez [html: null] et attendez le HTML. Ajout de ce commentaire afin que Google puisse indexer la réponse, espérons-le.
Donal Tobin

3
Vous pouvez toujours utiliser LSSerializer et sortir "UTF-8". Utilisez plutôt LSOutput avec StringWriter et définissez le type de codage sur "UTF- * 8"
ricosrealm

1
Fonctionne également avec l'objet Document w3c
troisième

2
<?xml version="1.0" encoding="UTF-16"?>déclaration dérange ... nous pouvons également ajouter cette ligne serializer .getDomConfig().setParameter("xml-declaration", false); dans la première solution ....
Tarsem Singh

merci pour votre réponse, c'est vraiment génial. Mais j'ai un problème avec cela, parfois certaines balises des parties correspondantes sont supprimées et leur contenu texte est affiché uniquement. Avez-vous des suggestions pour ce problème?
epcpu

16

Code simple de 4 lignes à obtenir String sans déclaration xml ( <?xml version="1.0" encoding="UTF-16"?>) deorg.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

Non pris en charge dans l'API JAXP standard, j'ai utilisé la bibliothèque JDom à cet effet. Il a une fonction imprimante, des options de formatage, etc. http://www.jdom.org/


+1 car ce n'est pas l'intention de l'API standard org.w3c.dom. Si je suis intéressé par les blocs de XML sous forme de texte, j'essaie généralement de l'analyser sous forme de texte avec une correspondance regex (si les critères de recherche sont facilement représentés sous forme de regex).
Cornel Masson

2

Si vous avez le schéma du XML ou pouvez autrement créer des liaisons JAXB pour celui-ci, vous pouvez utiliser JAXB Marshaller pour écrire dans 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

Essayez jcabi-xml avec une seule doublure:

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

Les nouvelles versions de jcabi-xml ne prennent pas en charge Element en tant que paramètre, uniquement Node / File / String.
Ermintar

1

voici ce qui se fait dans 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();
}

Et cela fonctionne pour moi!


0

Avec VTD-XML , vous pouvez passer dans le curseur et faire un seul appel à getElementFragment pour récupérer le segment (comme indiqué par son décalage et sa longueur) ... Ci-dessous un exemple

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

}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.