2009-09-06 10 views
93

Estoy utilizando el transformador XML integrado de Java para tomar un documento DOM e imprimir el XML resultante. El problema es que no está sangrando el texto en absoluto a pesar de haber establecido el parámetro "sangría" explícitamente.Java: cómo sangrar XML generado por Transformer

código de ejemplo

public class TestXML { 

public static void main(String args[]) throws Exception { 
    ByteArrayOutputStream s; 

    Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 
    Transformer t = TransformerFactory.newInstance().newTransformer(); 

    Element a,b; 

    a = d.createElement("a"); 
    b = d.createElement("b"); 

    a.appendChild(b); 

    d.appendChild(a); 

    t.setParameter(OutputKeys.INDENT, "yes"); 

    s = new ByteArrayOutputStream(); 

    t.transform(new DOMSource(d),new StreamResult(s)); 

    System.out.println(new String(s.toByteArray())); 

} 
} 

resultado

<?xml version="1.0" encoding="UTF-8" standalone="no"?><a><b/></a> 

resultado deseado

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<a> 
<b/> 
</a> 

Pensamientos?

Respuesta

184

necesita habilitar 'guión' y establecer la cantidad guión para el transformador:

t.setOutputProperty(OutputKeys.INDENT, "yes"); 
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 

Actualización:


Referencia: How to strip whitespace-only text nodes from a DOM before serialization?

(Muchas gracias a todos los miembros especialmente @ marc-novakowski, @ james-murty y @saad):

+7

oh hombre * cierra estén dirigidos hacia el escritorio * gracias – Mike

+62

parece tonto para mí que la indentación por defecto es 0, pero además de 'GUIÓN = sí' También tuve que agregar esto: 't.setOutputProperty (" {http://xml.apache.org/xslt}indent-amount "," 2 ");' – lapo

+1

Ten cuidado. Esta propiedad de sangría no funciona en java 5. lo hace en java 7. No lo ha intentado en java 6 – Hilikus

4

Si desea la sangría, debe especificarla en el TransformerFactory.

TransformerFactory tf = TransformerFactory.newInstance(); 
tf.setAttribute("indent-number", new Integer(2)); 
Transformer t = tf.newTransformer(); 
19

Ninguna de las soluciones sugeridas funcionó para mí. Así que seguí buscando una solución alternativa, que terminó siendo una mezcla de los dos antes mencionados y un tercer paso.

  1. establecer el número guión, en la TransformerFactory
  2. permitir que el guión en el transformador
  3. envolver el otuputstream con un escritor (o BufferedWriter)
//(1) 
TransformerFactory tf = TransformerFactory.newInstance(); 
tf.setAttribute("indent-number", new Integer(2)); 

//(2) 
Transformer t = tf.newTransformer(); 
t.setOutputProperty(OutputKeys.INDENT, "yes"); 

//(3) 
t.transform(new DOMSource(doc), 
new StreamResult(new OutputStreamWriter(out, "utf-8")); 

que debe hacer (3) para solucionar un comportamiento "erróneo" del código de manejo de xml.

Fuente: johnnymac75 @http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

(Si he citado mi fuente incorrectamente, que me haga saber)

+3

¿Qué significa "fuera" en la última línea? ¿a? – mujimu

+0

El paso 1 es el importante –

+0

'sangrado-número' no funcionará en Android. – Peterdk

13

El siguiente código está trabajando para mí con Java 7. fijo el guión (sí) y guión -montaje (2) en el transformador (no en la fábrica de transformadores) para que funcione.

TransformerFactory tf = TransformerFactory.newInstance(); 
Transformer t = tf.newTransformer(); 
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 
t.setOutputProperty(OutputKeys.INDENT, "yes"); 
t.transform(source, result); 

@ solución de mabac para establecer el atributo no funcionó para mí, pero de comentario @ lapo demostrado ser útiles.

+2

esta es la respuesta correcta. –

4

Utilicé la biblioteca Xerces (Apache) en lugar de jugar con Transformer. Una vez que agregue la biblioteca, agregue el código a continuación.

OutputFormat format = new OutputFormat(document); 
format.setLineWidth(65); 
format.setIndenting(true); 
format.setIndent(2); 
Writer outxml = new FileWriter(new File("out.xml")); 
XMLSerializer serializer = new XMLSerializer(outxml, format); 
serializer.serialize(document); 
+0

Funciona mejor, pero está en desuso. – rghome

+0

Sí. Intenté todos los otros enfoques con el Transformer pero todos rotos. Toda la biblioteca W3C es un desastre. Xerces funcionó. – Tuntable

5

import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory

transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "2"); 
1

Para mí añadiendo DOCTYPE_PUBLIC trabajaron:

transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes"); 
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "10"); 
+0

transformer.setOutputProperty (OutputKeys.DOCTYPE_PUBLIC, "yes"); es la clave – sector11

Cuestiones relacionadas