2011-02-04 21 views
16

¿Alguien sabe de un buen tutorial (o tiene un buen ejemplo) para escribir XML usando el marco SAX (o algo similar) y Java? La búsqueda ha arrojado muy poco en términos de resultados útiles. Estoy tratando de exportar desde una aplicación de Android y estoy buscando evitar la mayor cantidad de memoria posible.Generando XML usando SAX y Java

+0

SAX es un programa de análisis, que no genera nada :) – bestsss

+0

A menos que quiera absolutamente a use SAX (que de vez en cuando puede ser el caso cuando se procesan las tuberías), tal vez podría preguntar en términos más genéricos, es decir, ¿qué está tratando de lograr, en lugar de "cómo uso esta herramienta"? – StaxMan

+2

Lo que realmente estoy buscando es generar XML con la menor sobrecarga de memoria posible. He visto algunos ejemplos usando el marco SAX, pero no hay nada lo suficientemente concreto como para que una persona nueva de Java como yo lo encuentre útil. – Lunchbox

Respuesta

14

Hay una técnica muy útil para generar XML directamente desde POJOs a través del marco SAX (no es un analizador SAX, pero el Marco SAX). Esta técnica podría usarse para generar un documento XML.

Generar XML desde una estructura de datos arbitraria
http://download.oracle.com/javaee/1.4/tutorial/doc/JAXPXSLT5.html

En esencia, se añaden métodos para su POJO o escribir clase de utilidad para sus POJOs que los convierten en emisores de eventos SAX (emisor de eventos como un analizador SAX normalmente cuando analizar un documento XML). Ahora su "generador de eventos SAX" se parece al lado de salida de un analizador SAX y se le puede dar cualquier controlador de contenido que un analizador SAX tomaría, como uno que imprime XML con anterioridad. Pero también podría alimentar a un analizador DOM para generar un árbol DOM o alimentar a un motor XSLT para generar HTML o hacer una verdadera traducción XSL sin tener que generar primero un documento XML intermedio de los POJO.

Por ejemplo, una clase de persona podría tener un método emitXML() que incluyen estas líneas:

handler.startElement(nsu, PERSON_TAG, PERSON_TAG, NO_ATTRIBUTES); 

handler.startElement(nsu, FIRSTNAME_TAG, FIRSTNAME_TAG, atts); 
handler.characters(this.firstName.toCharArray(), 
     0, 
     this.firstName.length()); 
handler.endElement(nsu, FIRSTNAME_TAG, FIRSTNAME_TAG); 

... emit more instance variables 

... emit child object like: homeAddress.emitXML(handler, ...); 

handler.endElement(nsu, PERSON_TAG, PERSON_TAG); 

Actualización:

Un par de otras referencias:


Un par de respuestas a los comentarios:

Esto es cierto, pero la interfaz XMLStreamWriter descrito anteriormente es mucho más fácil -amistoso.- Michael Kay hace 3 horas

Sí, pero supongo que no estaba claro. Podría atravesar fácilmente la jerarquía y usar XMLStreamWriter para enviar directamente un documento XML a una secuencia. Sin embargo, los artículos muestran una poderosa técnica para atravesar la jerarquía y generar eventos SAX, en lugar de generar un documento XML directamente. Ahora puedo agregar diferentes manejadores de contenido que hacen cosas diferentes o generan diferentes versiones del XML. También podríamos alimentar nuestra jerarquía de objetos a cualquier herramienta que aceptara un analizador SAX, como un motor XSLT. Realmente solo aprovecha el patrón de visitantes establecido por el marco SAX: separamos la jerarquía de la salida del XML. Las partes que generan el XML, los manejadores de contenido, sin duda deben usar un XMLStreamWriter si su propósito es escribir un flujo XML.

Por ejemplo, en nuestro programa, enviamos mensajes XML a través de conectores de red entre componentes distribuidos y también utilizamos XSLT para generar nuestras páginas HTML. Previamente, recorrimos nuestra jerarquía para generar un documento XML (una cadena) y luego escribimos ese documento XML en un socket de red o alimentamos ese documento al motor XSLT (que básicamente solo lo analizó de nuevo). Después de usar esta técnica, podríamos esencialmente alimentar nuestra jerarquía de objetos (usando este adaptador SAX) directamente al motor XSLT sin necesitar la cadena XML intermedia. También fue conveniente poder utilizar un controlador de contenido para generar una representación XML compacta para la transmisión en red y usar una diferente para generar un documento XML bastante impreso para escribir en un archivo de registro.

Además, utilizar SAX parser API para escribir XML es un uso indebido de la API, en mi humilde opinión. - Puce hace 49 minutos

Quizás, pero creo que depende de sus necesidades. Si el requisito de OP es simplemente escribir un documento XML específico, entonces esto es definitivamente excesivo. Sin embargo, pensé que valía la pena mencionar si el OP usa XML de otras maneras en su proyecto que él no mencionó. No hay nada malo en lanzar una idea alternativa.

Llamar mal uso puede ser un poco fuerte, pero estoy de acuerdo en que tiene derecho a su opinión. Está documentado en un tutorial de Oracle, por lo que no se considera abuso por parte de los ingenieros de Sun/Oracle. Fue un gran éxito en nuestro proyecto para ayudarnos a cumplir con nuestros requisitos sin inconvenientes significativos, por lo que voy a mantener este enfoque en mi caja de herramientas para cuando sea útil en el futuro.

+3

Esto es cierto, pero la interfaz XMLStreamWriter descrita anteriormente es mucho más fácil de usar. –

+0

Además, usar SAX parser API para escribir XML es un uso indebido de la API, en mi humilde opinión. – Puce

+1

@Michael Kay - Gracias por tu comentario. Traté de aclarar en una edición anterior. –

32

El análisis SAX es para leer documentos, no para escribirlos.

Puede escribir XML con la XMLStreamWriter:

OutputStream outputStream = new FileOutputStream(new File("doc.xml")); 

XMLStreamWriter out = XMLOutputFactory.newInstance().createXMLStreamWriter(
       new OutputStreamWriter(outputStream, "utf-8")); 

out.writeStartDocument(); 
out.writeStartElement("doc"); 

out.writeStartElement("title"); 
out.writeCharacters("Document Title"); 
out.writeEndElement(); 

out.writeEndElement(); 
out.writeEndDocument(); 

out.close(); 
+0

Me gusta esta respuesta, desafortunadamente ese paquete no está disponible en Android. Mi culpa por no mencionar eso sin embargo. D: – Lunchbox

+2

Ok, puedes simplemente imprimir el XML manualmente. 'out.print (" valor ");' etc. Pero debe asegurarse de escaparse correctamente de los valores. Esto podría hacerse con Apache commons 'StringEscapeUtils.escapeXML()'. O algún otro método. Depende de los valores posibles, tal vez podrías hacerlo con expresiones regulares. – morja

5

A continuación respuestas "un buen tutorial para escribir XML usando el analizador SAX y Java" parte de la pregunta

no estoy seguro de si he pasado por esto Pero realmente me gusta Java's Really Big Index of Everything.

pasar por esto: http://download.oracle.com/javase/tutorial/jaxp/index.html

Y finalmente, esto: http://download.oracle.com/javase/tutorial/jaxp/sax/index.html

+0

Gracias Nishant. ¡Esta es información completa! Esto es lo que estaba buscando. – simpleDev

3

Considere también JAXB para escribir/leer XML.

4

Por favor, consulte mi publicación personal en el blog: XML Generation In Java - específicamente, The SAX method. Hace referencia a algunos otros artículos relacionados con esto, proporciona un ejemplo concreto y compara SAX con las otras API populares para generar XML de Java.

(Se dio cuenta de que esta es una pregunta anterior, pero consideró necesario agregar esto para cualquier otra persona que pueda tener la misma pregunta.)

1

También puede puente para trax con esto:

public abstract class PipedSAXSource extends SAXSource { 
    protected PipedSAXSource() { 
    setXMLReader(new CallWriteDuringSax()); 
    } 

    protected abstract void writeTo(ContentHandler sink) 
     throws IOException, SAXException; 

    private class CallWriteDuringSax extends XMLFilterImpl { 
    @Override 
    public void parse(InputSource ignored) throws IOException, SAXException { 
     writeTo(getContentHandler()); 
    } 

    @Override 
    public void setFeature(String name, boolean value) {} 
    } 
} 

uso de este modo:

public static void main(String[] args) throws Exception { 
    Source in = new PipedSAXSource() { 
     @Override 
     protected void writeTo(ContentHandler sink) throws SAXException { 
     sink.startDocument(); 

     sink.startElement("", "root", "root", new AttributesImpl()); 
     sink.endElement("", "root", "root"); 

     sink.endDocument(); 
     } 
    }; 

    Transformer identity = TransformerFactory.newInstance().newTransformer(); 
    identity.transform(in, new StreamResult(System.out)); 
    } 
Cuestiones relacionadas