Pregunta

Estoy buscando el mejor método para analizar varios documentos XML utilizando una aplicación Java.Actualmente estoy haciendo esto con SAX y un controlador de contenido personalizado y funciona muy bien: rápido y estable.

He decidido explorar la opción de que el mismo programa, que actualmente recibe un documento XML de formato único, reciba dos formatos de documento XML adicionales, con varios cambios de elementos XML.Esperaba simplemente cambiar el ContentHandler por uno apropiado basado en el primer "startElement" del documento...pero, claro, el ContentHandler está configurado y entonces ¡El documento está analizado!

... constructor ...
{
SAXParserFactory spf = SAXParserFactory.newInstance();

try {
SAXParser sp = spf.newSAXParser();
parser = sp.getXMLReader();
parser.setErrorHandler(new MyErrorHandler());
} catch (Exception e) {} 

... parse StringBuffer ...
try {
parser.setContentHandler(pP);
parser.parse(new InputSource(new StringReader(xml.toString())));
return true;
} catch (IOException e) {
    e.printStackTrace();
} catch (SAXException e) {
    e.printStackTrace();
}
...

Entonces, no parece que pueda hacer esto de la manera que inicialmente pensé que podría hacerlo.

Dicho esto, ¿estoy viendo esto completamente mal?¿Cuál es el mejor método para analizar múltiples documentos XML discretos con el mismo código de manejo XML? Intenté preguntar en una publicación más general antes...pero creo que estaba siendo demasiado vago.Por motivos de velocidad y eficiencia, nunca miré realmente el DOM porque estos documentos XML son bastante grandes y el sistema recibe alrededor de 1200 cada pocos minutos.Es solo un envío de información unidireccional.

Para hacer esta pregunta demasiado larga y aumentar mi confusión;A continuación se muestra una maqueta de varios documentos XML que me gustaría tener como un solo SAX, StAX o ??el analizador trata limpiamente.

productos.xml:

<products>
<product>
  <id>1</id>
  <name>Foo</name>
<product>
  <id>2</id>
  <name>bar</name>
</product>
</products>

tiendas.xml:

<stores>
<store>
  <id>1</id>
  <name>S1A</name>
  <location>CA</location>
</store>
<store>
  <id>2</id>
  <name>A1S</name>
  <location>NY</location>
</store>
</stores>

administradores.xml:

<managers>
<manager>
  <id>1</id>
  <name>Fen</name>
  <store>1</store>
</manager>
<manager>
  <id>2</id>
  <name>Diz</name>
  <store>2</store>
</manager>
</managers>
¿Fue útil?

Solución

Según tengo entendido, el problema es que no se sabe qué formato tiene el documento antes de analizarlo.Podrías usar un patrón de delegado.Supongo que no está validando con un DTD/XSD/etc. y que está bien que DefaultHandler tenga estado.

public class DelegatingHandler extends DefaultHandler {

    private Map<String, DefaultHandler> saxHandlers;
    private DefaultHandler delegate = null;

    public DelegatingHandler(Map<String, DefaultHandler> delegates) {
        saxHandlers = delegates;
    }

    @Override
    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
       if(delegate == null) {
           delegate = saxHandlers.get(name);
       }
       delegate.startElement(uri, localName, name, attributes);
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException {
        delegate.endElement(uri, localName, name);
    }

//etcetera...

Otros consejos

Has hecho un buen trabajo al explicar lo que quieres hacer, pero no por qué.Existen varios marcos XML que simplifican la clasificación y desclasificación de objetos Java hacia/desde XML.

El más simple es Digestor de bienes comunes que normalmente uso para analizar archivos de configuración.Pero si desea trabajar con objetos Java, entonces debería mirar Castor, JiBX, JAXB, Frijoles XML, XStream, o algo similar.Castor o JiBX son mis dos favoritos.

Probé SAXParser una vez, pero una vez encontré XStream Nunca volví a eso.Con XStream puedes crear objetos Java y convertirlos a XML.Envíelos y use XStream para recrear el objeto.Muy fácil de usar, rápido y crea XML limpio.

De cualquier manera, debe saber qué datos recibirá del archivo XML.Puede enviarlos de diferentes maneras para saber qué analizador utilizar.O tener un objeto de datos que pueda contener todo, pero solo se completa una estructura (producto/tienda/administradores).Quizás algo como:

public class DataStructure {

    List<ProductStructure> products;

    List<StoreStructure> stors;

    List<ManagerStructure> managers;

    ...

    public int getProductCount() {
        return products.lenght();
    }

    ...
}

Y con XStream, convierta a XML, envíe y luego vuelva a crear el objeto.Luego haz lo que quieras con él.

Consulte la documentación para XMLReader.setContentHandler(), dice:

Las aplicaciones pueden registrar un controlador nuevo o diferente en medio de un análisis, y el analizador SAX debe comenzar a utilizar el nuevo controlador inmediatamente.

Por lo tanto, debería poder crear un SelectorContentHandler que consume eventos hasta el primero startElement evento, basado en eso cambia el ContentHandler en el lector XML y pasa el primer evento del elemento inicial al nuevo controlador de contenido.Sólo tienes que pasar el XMLReader hacia SelectorContentHandler en el constructor.Si necesitas todo los eventos que se pasarán al controlador de contenido específico del vocabulario, SelectorContentHandler tiene que almacenar en caché los eventos y luego pasarlos, pero en la mayoría de los casos esto no es necesario.

Como nota al margen, últimamente he usado XOM En casi todos mis proyectos para manejar XML, hasta ahora el rendimiento no ha sido el problema.

JAXB.La arquitectura Java para el enlace XML.Básicamente, creas un xsd que define tu diseño XML (creo que también podrías usar un DTD).Luego pasa el XSD al compilador JAXB y el compilador crea clases Java para organizar y descomponer su documento XML en objetos Java.Es realmente sencillo.

Por cierto, existen opciones de línea de comando para jaxb para especificar el nombre del paquete en el que desea colocar las clases resultantes, etc.

Si desea un manejo más dinámico, el enfoque Stax probablemente funcione mejor que Sax.Eso sigue siendo un nivel bastante bajo;Si quieres un enfoque más sencillo, XStream y JAXB son mis favoritos.Pero sí requieren objetos bastante rígidos para mapearlos.

De acuerdo con StaxMan, quien curiosamente quiere que uses Stax.Es un analizador basado en extracción en lugar del de inserción que está utilizando actualmente.Sin embargo, esto requeriría algunos cambios significativos en su código.

:-)

Sí, tengo cierta parcialidad hacia Stax.Pero como dije, muchas veces el enlace de datos es más conveniente que la solución de transmisión.Pero si lo que desea es transmisión y no necesita canalización (de múltiples etapas de filtrado), Stax es más simple que SAX.

Una cosa más:Por muy bueno que sea XOM (alternativas wrt), a menudo el modelo de árbol no es lo correcto si no se trata de xml "centrado en documentos" (~= páginas xhtml, docbook, documentos de oficina abiertos).Para el intercambio de datos, archivos de configuración, etc., el enlace de datos es más conveniente, más eficiente y más natural.Simplemente diga no a los modelos de árbol como DOM para estos casos de uso.Entonces, JAXB, XStream, JibX son buenos.O, para un gusto más adquirido, digester, castor, xmlbeans.

VTD-XML es conocido por ser la mejor tecnología de procesamiento XML para procesamiento XML pesado.Consulte la referencia a continuación para obtener una prueba.

http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top