Proporcionaré una respuesta general orientada a preguntas y respuestas para esta pregunta:
Respuesta a preguntas
¿Por qué necesitamos un analizador XML?
Necesitamos un analizador XML porque no queremos hacer todo en nuestra aplicación desde cero, y necesitamos algunos programas o bibliotecas "auxiliares" para hacer algo de muy bajo nivel pero muy necesario para nosotros. Estas cosas de bajo nivel pero necesarias incluyen verificar la buena formabilidad, validar el documento contra su DTD o esquema (solo para validar analizadores), resolver la referencia de caracteres, comprender las secciones CDATA, etc. Los analizadores XML son programas de "ayuda" y harán todos estos trabajos. Con el analizador XML, estamos protegidos de muchas de estas complejidades y podríamos concentrarnos solo en la programación de alto nivel a través de las API implementadas por los analizadores, y así ganar eficiencia en la programación.
¿Cuál es mejor, SAX o DOM?
Tanto el analizador SAX como DOM tienen sus ventajas y desventajas. Cuál es mejor debería depender de las características de su aplicación (consulte algunas preguntas a continuación).
¿Qué analizador puede obtener mejores analizadores de velocidad, DOM o SAX?
El analizador SAX puede obtener una mejor velocidad.
¿Cuál es la diferencia entre API basada en árbol y API basada en eventos?
Una API basada en árbol se centra en una estructura de árbol y, por lo tanto, proporciona interfaces en los componentes de un árbol (que es un documento DOM), como la interfaz de documento, la interfaz de nodo, la interfaz de NodeList, la interfaz de Element, la interfaz de Attr, etc. Sin embargo, por el contrario, una API basada en eventos proporciona interfaces en los controladores. Hay cuatro interfaces de controlador, la interfaz ContentHandler, la interfaz DTDHandler, la interfaz EntityResolver y la interfaz ErrorHandler.
¿Cuál es la diferencia entre un analizador DOM y un analizador SAX?
Los analizadores DOM y los analizadores SAX funcionan de diferentes maneras:
Un analizador DOM crea una estructura de árbol en la memoria del documento de entrada y luego espera las solicitudes del cliente. Pero un analizador SAX no crea ninguna estructura interna. En cambio, toma las ocurrencias de componentes de un documento de entrada como eventos, y le dice al cliente lo que lee mientras lee el documento de entrada. UNA
El analizador DOM siempre sirve a la aplicación del cliente con todo el documento, sin importar cuánto sea realmente necesario para el cliente. Pero un analizador SAX sirve la aplicación cliente siempre solo con partes del documento en un momento dado.
- Con el analizador DOM, las llamadas a métodos en la aplicación cliente deben ser explícitas y formar una especie de cadena. Pero con SAX, algunos métodos determinados (generalmente anulados por el cliente) se invocarán automáticamente (implícitamente) de una manera que se llama "devolución de llamada" cuando ocurren ciertos eventos. El cliente no tiene que llamar explícitamente estos métodos, aunque podríamos llamarlos explícitamente.
¿Cómo decidimos qué analizador es bueno?
Idealmente, un buen analizador debe ser rápido (eficiente en tiempo), eficiente en espacio, rico en funcionalidad y fácil de usar. Pero en realidad, ninguno de los analizadores principales tiene todas estas características al mismo tiempo. Por ejemplo, un analizador DOM es rico en funcionalidad (porque crea un árbol DOM en la memoria y le permite acceder a cualquier parte del documento repetidamente y le permite modificar el árbol DOM), pero es poco eficiente cuando el documento es enorme , y lleva un poco de tiempo aprender a trabajar con él. Sin embargo, un analizador SAX es mucho más eficiente en el espacio en caso de un gran documento de entrada (porque no crea una estructura interna). Además, se ejecuta más rápido y es más fácil de aprender que DOM Parser porque su API es realmente simple. Pero desde el punto de vista de la funcionalidad, proporciona menos funciones, lo que significa que los propios usuarios deben cuidar más, como crear sus propias estructuras de datos. Por cierto, ¿qué es un buen analizador? Creo que la respuesta realmente depende de las características de su aplicación.
¿Cuáles son algunas aplicaciones del mundo real en las que usar el analizador SAX es ventajoso que usar el analizador DOM y viceversa? ¿Cuáles son las aplicaciones habituales para un analizador DOM y para un analizador SAX?
En los siguientes casos, usar el analizador SAX es ventajoso que usar el analizador DOM.
- El documento de entrada es demasiado grande para la memoria disponible (en este caso, SAX es su única opción)
- Puede procesar el documento en pequeños fragmentos de entrada contiguos. No necesita todo el documento antes de poder hacer un trabajo útil.
- Solo desea usar el analizador para extraer la información de interés, y todos sus cálculos se basarán completamente en las estructuras de datos creadas por usted mismo. En realidad, en la mayoría de nuestras aplicaciones, creamos estructuras de datos propias que generalmente no son tan complicadas como el árbol DOM. Desde este sentido, creo, la posibilidad de usar un analizador DOM es menor que la de usar un analizador SAX.
En los siguientes casos, usar el analizador DOM es ventajoso que usar el analizador SAX.
- Su aplicación necesita acceder a partes del documento ampliamente separadas al mismo tiempo.
- Es probable que su aplicación utilice una estructura de datos interna que es casi tan complicada como el documento mismo.
- Su aplicación tiene que modificar el documento repetidamente.
- Su aplicación tiene que almacenar el documento durante un período de tiempo significativo a través de muchas llamadas a métodos.
Ejemplo (¿Usar un analizador DOM o un analizador SAX?):
Suponga que un instructor tiene un documento XML que contiene toda la información personal de los estudiantes, así como los puntos que sus estudiantes hicieron en su clase, y ahora está asignando calificaciones finales para los estudiantes usando una aplicación. Lo que quiere producir es una lista con el SSN y las calificaciones. También suponemos que en su aplicación, el instructor no utiliza ninguna estructura de datos, como las matrices, para almacenar la información personal del alumno y los puntos. Si el instructor decide dar A a aquellos que obtuvieron el promedio de la clase o más, y dar B a los demás, entonces será mejor que use un analizador DOM en su aplicación. La razón es que no tiene forma de saber cuánto es el promedio de la clase antes de que se procese todo el documento. Lo que probablemente deba hacer en su solicitud es primero revisar todos los estudiantes puntos y calcular el promedio, y luego revisar el documento nuevamente y asignar la calificación final a cada estudiante comparando los puntos que obtuvo con el promedio de la clase. Sin embargo, si el instructor adopta una política de calificación tal que los estudiantes que obtuvieron 90 puntos o más, se les asigne A y a los demás se les asigne B, entonces probablemente sea mejor que use un analizador SAX. La razón es que, para asignar a cada estudiante una calificación final, no necesita esperar a que se procese todo el documento. Podría asignarle inmediatamente una calificación a un estudiante una vez que el analizador SAX lea la calificación de este estudiante. En el análisis anterior, asumimos que el instructor no creó ninguna estructura de datos propia. ¿Qué pasa si crea su propia estructura de datos, como un conjunto de cadenas para almacenar el SSN y un conjunto de enteros para almacenar los puntos? En este caso, Creo que SAX es una mejor opción, antes de que esto también pueda ahorrar memoria y tiempo, pero hacer el trabajo. Bueno, una consideración más en este ejemplo. ¿Qué sucede si lo que quiere hacer el instructor no es imprimir una lista, sino volver a guardar el documento original con la calificación de cada alumno actualizada? En este caso, un analizador DOM debería ser una mejor opción sin importar la política de calificación que esté adoptando. No necesita crear ninguna estructura de datos propia. Lo que debe hacer es modificar primero el árbol DOM (es decir, establecer el valor en el nodo 'grado') y luego guardar todo el árbol modificado. Si elige usar un analizador SAX en lugar de un analizador DOM, en este caso tiene que crear una estructura de datos que sea casi tan complicada como un árbol DOM antes de poder hacer el trabajo. pero haz el trabajo. Bueno, una consideración más en este ejemplo. ¿Qué sucede si lo que quiere hacer el instructor no es imprimir una lista, sino volver a guardar el documento original con la calificación de cada alumno actualizada? En este caso, un analizador DOM debería ser una mejor opción sin importar la política de calificación que esté adoptando. No necesita crear ninguna estructura de datos propia. Lo que debe hacer es modificar primero el árbol DOM (es decir, establecer el valor en el nodo 'grado') y luego guardar todo el árbol modificado. Si elige usar un analizador SAX en lugar de un analizador DOM, en este caso tiene que crear una estructura de datos que sea casi tan complicada como un árbol DOM antes de poder hacer el trabajo. pero haz el trabajo. Bueno, una consideración más en este ejemplo. ¿Qué sucede si lo que quiere hacer el instructor no es imprimir una lista, sino volver a guardar el documento original con la calificación de cada alumno actualizada? En este caso, un analizador DOM debería ser una mejor opción sin importar la política de calificación que esté adoptando. No necesita crear ninguna estructura de datos propia. Lo que debe hacer es modificar primero el árbol DOM (es decir, establecer el valor en el nodo 'grado') y luego guardar todo el árbol modificado. Si elige usar un analizador SAX en lugar de un analizador DOM, en este caso tiene que crear una estructura de datos que sea casi tan complicada como un árbol DOM antes de poder hacer el trabajo. pero para guardar el documento original con la calificación de cada estudiante actualizada? En este caso, un analizador DOM debería ser una mejor opción sin importar la política de calificación que esté adoptando. No necesita crear ninguna estructura de datos propia. Lo que debe hacer es modificar primero el árbol DOM (es decir, establecer el valor en el nodo 'grado') y luego guardar todo el árbol modificado. Si elige usar un analizador SAX en lugar de un analizador DOM, en este caso tiene que crear una estructura de datos que sea casi tan complicada como un árbol DOM antes de poder hacer el trabajo. pero para guardar el documento original con la calificación de cada estudiante actualizada? En este caso, un analizador DOM debería ser una mejor opción sin importar la política de calificación que esté adoptando. No necesita crear ninguna estructura de datos propia. Lo que debe hacer es modificar primero el árbol DOM (es decir, establecer el valor en el nodo 'grado') y luego guardar todo el árbol modificado. Si elige usar un analizador SAX en lugar de un analizador DOM, en este caso tiene que crear una estructura de datos que sea casi tan complicada como un árbol DOM antes de poder hacer el trabajo. nodo) y luego guarde todo el árbol modificado. Si elige usar un analizador SAX en lugar de un analizador DOM, en este caso tiene que crear una estructura de datos que sea casi tan complicada como un árbol DOM antes de poder hacer el trabajo. nodo) y luego guarde todo el árbol modificado. Si elige usar un analizador SAX en lugar de un analizador DOM, en este caso tiene que crear una estructura de datos que sea casi tan complicada como un árbol DOM antes de poder hacer el trabajo.
Un ejemplo
Planteamiento del problema : escriba un programa Java para extraer toda la información sobre círculos que son elementos en un documento XML dado. Suponemos que cada elemento del círculo tiene tres elementos secundarios (es decir, x, y y radio), así como un atributo de color. A continuación se muestra un documento de muestra:
<?xml version="1.0"?>
<!DOCTYPE shapes [
<!ELEMENT shapes (circle)*>
<!ELEMENT circle (x,y,radius)>
<!ELEMENT x (#PCDATA)>
<!ELEMENT y (#PCDATA)>
<!ELEMENT radius (#PCDATA)>
<!ATTLIST circle color CDATA #IMPLIED>
]>
<shapes>
<circle color="BLUE">
<x>20</x>
<y>20</y>
<radius>20</radius>
</circle>
<circle color="RED" >
<x>40</x>
<y>40</y>
<radius>20</radius>
</circle>
</shapes>
Programa con DOMparser
import java.io.*;
import org.w3c.dom.*;
import org.apache.xerces.parsers.DOMParser;
public class shapes_DOM {
static int numberOfCircles = 0; // total number of circles seen
static int x[] = new int[1000]; // X-coordinates of the centers
static int y[] = new int[1000]; // Y-coordinates of the centers
static int r[] = new int[1000]; // radius of the circle
static String color[] = new String[1000]; // colors of the circles
public static void main(String[] args) {
try{
// create a DOMParser
DOMParser parser=new DOMParser();
parser.parse(args[0]);
// get the DOM Document object
Document doc=parser.getDocument();
// get all the circle nodes
NodeList nodelist = doc.getElementsByTagName("circle");
numberOfCircles = nodelist.getLength();
// retrieve all info about the circles
for(int i=0; i<nodelist.getLength(); i++) {
// get one circle node
Node node = nodelist.item(i);
// get the color attribute
NamedNodeMap attrs = node.getAttributes();
if(attrs.getLength() > 0)
color[i]=(String)attrs.getNamedItem("color").getNodeValue();
// get the child nodes of a circle node
NodeList childnodelist = node.getChildNodes();
// get the x and y value
for(int j=0; j<childnodelist.getLength(); j++) {
Node childnode = childnodelist.item(j);
Node textnode = childnode.getFirstChild();//the only text node
String childnodename=childnode.getNodeName();
if(childnodename.equals("x"))
x[i]= Integer.parseInt(textnode.getNodeValue().trim());
else if(childnodename.equals("y"))
y[i]= Integer.parseInt(textnode.getNodeValue().trim());
else if(childnodename.equals("radius"))
r[i]= Integer.parseInt(textnode.getNodeValue().trim());
}
}
// print the result
System.out.println("circles="+numberOfCircles);
for(int i=0;i<numberOfCircles;i++) {
String line="";
line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
System.out.println(line);
}
} catch (Exception e) {e.printStackTrace(System.err);}
}
}
Programa con SAXparser
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;
public class shapes_SAX extends DefaultHandler {
static int numberOfCircles = 0; // total number of circles seen
static int x[] = new int[1000]; // X-coordinates of the centers
static int y[] = new int[1000]; // Y-coordinates of the centers
static int r[] = new int[1000]; // radius of the circle
static String color[] = new String[1000]; // colors of the circles
static int flagX=0; //to remember what element has occurred
static int flagY=0; //to remember what element has occurred
static int flagR=0; //to remember what element has occurred
// main method
public static void main(String[] args) {
try{
shapes_SAX SAXHandler = new shapes_SAX (); // an instance of this class
SAXParser parser=new SAXParser(); // create a SAXParser object
parser.setContentHandler(SAXHandler); // register with the ContentHandler
parser.parse(args[0]);
} catch (Exception e) {e.printStackTrace(System.err);} // catch exeptions
}
// override the startElement() method
public void startElement(String uri, String localName,
String rawName, Attributes attributes) {
if(rawName.equals("circle")) // if a circle element is seen
color[numberOfCircles]=attributes.getValue("color"); // get the color attribute
else if(rawName.equals("x")) // if a x element is seen set the flag as 1
flagX=1;
else if(rawName.equals("y")) // if a y element is seen set the flag as 2
flagY=1;
else if(rawName.equals("radius")) // if a radius element is seen set the flag as 3
flagR=1;
}
// override the endElement() method
public void endElement(String uri, String localName, String rawName) {
// in this example we do not need to do anything else here
if(rawName.equals("circle")) // if a circle element is ended
numberOfCircles += 1; // increment the counter
}
// override the characters() method
public void characters(char characters[], int start, int length) {
String characterData =
(new String(characters,start,length)).trim(); // get the text
if(flagX==1) { // indicate this text is for <x> element
x[numberOfCircles] = Integer.parseInt(characterData);
flagX=0;
}
else if(flagY==1) { // indicate this text is for <y> element
y[numberOfCircles] = Integer.parseInt(characterData);
flagY=0;
}
else if(flagR==1) { // indicate this text is for <radius> element
r[numberOfCircles] = Integer.parseInt(characterData);
flagR=0;
}
}
// override the endDocument() method
public void endDocument() {
// when the end of document is seen, just print the circle info
System.out.println("circles="+numberOfCircles);
for(int i=0;i<numberOfCircles;i++) {
String line="";
line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
System.out.println(line);
}
}
}