¿Cómo puedo generar org.w3c.dom.Element en formato de cadena en java?

89

Tengo un org.w3c.dom.Elementobjeto pasado a mi método. Necesito ver toda la cadena xml, incluidos sus nodos secundarios (todo el gráfico del objeto). Estoy buscando un método que pueda convertir el Elementen una cadena de formato xml que pueda System.out.println. Solo println()en el objeto 'Elemento' no funcionará porque toString()no generará el formato xml y no pasará por su nodo secundario. ¿Existe una manera fácil sin escribir mi propio método para hacer eso? Gracias.

Doug Porter
fuente

Respuestas:

155

Suponiendo que quiera seguir con la API estándar ...

Podrías usar un DOMImplementationLS :

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

Si la declaración <? Xml version = "1.0" encoding = "UTF-16"?> Le molesta, podría usar un transformador en su lugar:

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
fuente
7
Esta es la solución si obtiene [html: null] y espera el HTML. Agregué este comentario para que Google pueda indexar la respuesta con suerte.
Donal Tobin
3
Aún puede usar LSSerializer y generar "UTF-8". Use LSOutput con StringWriter en su lugar y establezca el tipo de codificación en "UTF- * 8"
ricosrealm
1
También funciona con el objeto de documento w3c
tercero
2
<?xml version="1.0" encoding="UTF-16"?>la declaración molesta ... también podemos agregar esta línea serializer .getDomConfig().setParameter("xml-declaration", false); en la primera solución ....
Tarsem Singh
gracias por tu respuesta, eso es realmente genial. Pero tengo un problema con él, a veces se eliminan algunas etiquetas de las partes coincidentes y el contenido de texto de ellas se muestra únicamente. ¿Tiene alguna sugerencia para este problema?
epcpu
16

Código simple de 4 líneas para obtener String sin declaración 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);
Tarsem Singh
fuente
2

No es compatible con la API JAXP estándar, utilicé la biblioteca JDom para este propósito. Tiene una función de impresora, opciones de formateador, etc. http://www.jdom.org/

Karl
fuente
+1 porque no es la intención de la API org.w3c.dom estándar. Si estoy interesado en bloques de XML como texto, generalmente trato de analizarlo como texto con una expresión regular (si el criterio de búsqueda se representa fácilmente como una expresión regular).
Cornel Masson
2

Si tiene el esquema del XML o puede crear enlaces JAXB para él, puede usar JAXB Marshaller para escribir en 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
fuente
2

Pruebe jcabi-xml con una línea:

String xml = new XMLDocument(element).toString();
yegor256
fuente
Las nuevas versiones de jcabi-xml no admiten Element como parámetro, solo Node / File / String.
Ermintar
1

esto es lo que se hace en 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();
}

¡Y funciona para mi!

trueno
fuente
0

Con VTD-XML , puede pasar al cursor y realizar una única llamada a getElementFragment para recuperar el segmento (como se indica por su desplazamiento y longitud) ... A continuación se muestra un ejemplo

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-autor
fuente