Qual é a maneira mais curta de imprimir um org.w3c.dom.Document em stdout?

103

Qual é a maneira mais fácil de imprimir corretamente (também conhecido como formatado) org.w3c.dom.Documentem stdout?

flybywire
fonte

Respostas:

186

Call printDocument(doc, System.out), onde esse método se parece com este:

public static void printDocument(Document doc, OutputStream out) throws IOException, TransformerException {
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

    transformer.transform(new DOMSource(doc), 
         new StreamResult(new OutputStreamWriter(out, "UTF-8")));
}

(O indent-amounté opcional e pode não funcionar com sua configuração específica)

Bozho
fonte
64
Não é irônico que essa seja a maneira "mais fácil" de simplesmente imprimir um documento XML em Java?
Thomas
7
por outro lado, você tem bastante controle;)
Bozho
2
Brilhante! E sim, é um pouco demais de texto, mas é cristalino quais são as opções selecionadas e Eclipse / Netbeans realmente ajudam você a escrever isso. Mostre-me uma versão menor e direi o que ela não pode fazer. Pior, direi onde você precisa de 3 rodadas de depuração para acertar ...
Peter Kriens
4
Juro por Deus, Java .. me faça escrever um número ridículo de linhas de código para algo que pode ser feito em uma ou duas em outras linguagens ... com controle total também ..
l46kok
Mas se seu XML contiver caracteres astrais e você estiver usando Xalan, observe issues.apache.org/jira/browse/XALANJ-2419 e consulte também stackoverflow.com/a/11987283/1031689
JasonPlutext
13

E se:

OutputFormat format = new OutputFormat(doc);
format.setIndenting(true);
XMLSerializer serializer = new XMLSerializer(System.out, format);
serializer.serialize(doc);
Dennis
fonte
8
Embora mais fácil, essa abordagem requer Xerces
Pace
3
Posso acrescentar que hoje XMLSerializer e OutputFormat estão obsoletos
Vokail
9

Experimente jcabi-xml com um liner:

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

Esta é a dependência de que você precisa:

<dependency>
  <groupId>com.jcabi</groupId>
  <artifactId>jcabi-xml</artifactId>
  <version>0.14</version>
</dependency>
Yegor256
fonte
4
private void printNode(Node rootNode, String spacer) {
    System.out.println(spacer + rootNode.getNodeName() + " -> " + rootNode.getNodeValue());
    NodeList nl = rootNode.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++)
        printNode(nl.item(i), spacer + "   ");
}
Hannes
fonte
1
Agradeço que o Q peça o mais curto, mas (para o benefício de qualquer outra pessoa) talvez você possa elaborar sua resposta para explicar o que está acontecendo?
Andrew
html -> head -> meta -> title -> body -> Se eu colocar um espaço de string como o espaçador acima é o resultado que obtenho. É o que se pretende fazer? Uma impressão completa do XML é o que é necessário, eu acho, quando significa bem impresso.
jeraldfdo
0

Isso retornará uma saída bem formatada usando descida / subida recursiva.

private static boolean skipNL;
private static String printXML(Node rootNode) {
    String tab = "";
    skipNL = false;
    return(printXML(rootNode, tab));
}
private static String printXML(Node rootNode, String tab) {
    String print = "";
    if(rootNode.getNodeType()==Node.ELEMENT_NODE) {
        print += "\n"+tab+"<"+rootNode.getNodeName()+">";
    }
    NodeList nl = rootNode.getChildNodes();
    if(nl.getLength()>0) {
        for (int i = 0; i < nl.getLength(); i++) {
            print += printXML(nl.item(i), tab+"  ");    // \t
        }
    } else {
        if(rootNode.getNodeValue()!=null) {
            print = rootNode.getNodeValue();
        }
        skipNL = true;
    }
    if(rootNode.getNodeType()==Node.ELEMENT_NODE) {
        if(!skipNL) {
            print += "\n"+tab;
        }
        skipNL = false;
        print += "</"+rootNode.getNodeName()+">";
    }
    return(print);
}
Marca
fonte
Isso está muito incompleto.
Andrew,
-1

se você usar dom4j, será dom4JDOM.asString ()

Rockoder
fonte