Fornecerei uma resposta geral orientada para perguntas e respostas para esta pergunta:
Resposta a perguntas
Por que precisamos do analisador XML?
Precisamos do analisador XML, porque não queremos fazer tudo em nosso aplicativo do zero e precisamos de alguns programas ou bibliotecas "auxiliares" para fazer algo de nível muito baixo, mas muito necessário para nós. Essas coisas de baixo nível, mas necessárias, incluem verificar a boa formação, validar o documento com relação ao seu DTD ou esquema (apenas para validar analisadores), resolver a referência de caracteres, entender as seções CDATA e assim por diante. Os analisadores XML são exatamente esses programas "auxiliares" e farão todos esses trabalhos. Com o analisador XML, somos protegidos de muitas dessas complexidades e podemos nos concentrar em apenas programar em alto nível através das APIs implementadas pelos analisadores e, assim, obter eficiência na programação.
Qual é o melhor, SAX ou DOM?
O analisador SAX e DOM têm suas vantagens e desvantagens. Qual é o melhor deve depender das características do seu aplicativo (consulte algumas perguntas abaixo).
Qual analisador pode obter melhor velocidade, analisadores DOM ou SAX?
O analisador SAX pode obter melhor velocidade.
Qual é a diferença entre API baseada em árvore e API baseada em eventos?
Uma API baseada em árvore é centralizada em uma estrutura de árvore e, portanto, fornece interfaces nos componentes de uma árvore (que é um documento DOM), como interface de documento, interface de nó, interface de NodeList, interface de elemento, interface de atributo e assim por diante. Por outro lado, no entanto, uma API baseada em eventos fornece interfaces nos manipuladores. Existem quatro interfaces de manipulador, interface ContentHandler, interface DTDHandler, interface EntityResolver e interface ErrorHandler.
Qual é a diferença entre um analisador DOM e um analisador SAX?
Analisadores DOM e SAX funcionam de diferentes maneiras:
Um analisador DOM cria uma estrutura em árvore na memória a partir do documento de entrada e aguarda solicitações do cliente. Mas um analisador SAX não cria nenhuma estrutura interna. Em vez disso, considera as ocorrências dos componentes de um documento de entrada como eventos e informa ao cliente o que ele lê ao ler o documento de entrada. UMA
O analisador DOM sempre atende ao aplicativo cliente com o documento inteiro, independentemente do quanto seja realmente necessário ao cliente. Mas um analisador SAX atende ao aplicativo cliente sempre apenas com partes do documento a qualquer momento.
- Com o analisador DOM, as chamadas de método no aplicativo cliente precisam ser explícitas e formar um tipo de cadeia. Porém, com o SAX, alguns métodos (geralmente substituídos pelo cientista) serão invocados automaticamente (implicitamente) de uma maneira que é chamada de "retorno de chamada" quando ocorrem certos eventos. Esses métodos não precisam ser chamados explicitamente pelo cliente, embora possamos chamá-los explicitamente.
Como decidimos qual analisador é bom?
Idealmente, um bom analisador deve ser rápido (econômico em termos de tempo), econômico em espaço, rico em funcionalidades e fácil de usar. Mas, na realidade, nenhum dos principais analisadores possui todos esses recursos ao mesmo tempo. Por exemplo, um Analisador DOM é rico em funcionalidade (porque cria uma árvore DOM na memória e permite acessar qualquer parte do documento repetidamente e permite modificar a árvore DOM), mas é ineficiente em termos de espaço quando o documento é enorme , e leva um pouco de tempo para aprender a trabalhar com ele. Um analisador SAX, no entanto, é muito mais eficiente em termos de espaço no caso de grandes documentos de entrada (porque não cria estrutura interna). Além disso, ele roda mais rápido e é mais fácil de aprender do que o Analisador DOM, porque sua API é realmente simples. Mas do ponto de vista da funcionalidade, fornece menos funções, o que significa que os próprios usuários precisam cuidar de mais, como criar suas próprias estruturas de dados. A propósito, o que é um bom analisador? Eu acho que a resposta realmente depende das características do seu aplicativo.
Quais são alguns aplicativos do mundo real em que o uso do analisador SAX é vantajoso do que o uso do analisador DOM e vice-versa? Qual é o aplicativo usual para um analisador DOM e para um analisador SAX?
Nos seguintes casos, usar o analisador SAX é vantajoso do que usar o analisador DOM.
- O documento de entrada é muito grande para a memória disponível (na verdade, neste caso, o SAX é sua única opção)
- Você pode processar o documento em pequenos pedaços contíguos de entrada. Você não precisa de todo o documento antes de poder realizar um trabalho útil
- Você só deseja usar o analisador para extrair as informações de seu interesse e todo o seu cálculo será completamente baseado nas estruturas de dados criadas por você. Na verdade, na maioria dos aplicativos, criamos estruturas de dados próprias, que geralmente não são tão complicadas quanto a árvore DOM. Nesse sentido, acho, a chance de usar um analisador DOM é menor do que a de usar um analisador SAX.
Nos seguintes casos, usar o analisador DOM é vantajoso do que usar o analisador SAX.
- Seu aplicativo precisa acessar partes do documento amplamente separadamente ao mesmo tempo.
- Seu aplicativo provavelmente pode usar uma estrutura de dados interna quase tão complicada quanto o próprio documento.
- Seu aplicativo precisa modificar o documento repetidamente.
- Seu aplicativo precisa armazenar o documento por um período significativo de tempo por meio de várias chamadas de método.
Exemplo (Use um analisador DOM ou SAX?):
Suponha que um instrutor tenha um documento XML que contenha todas as informações pessoais dos alunos, bem como os pontos que seus alunos fizeram em sua classe, e agora ele está atribuindo notas finais para os alunos usando um aplicativo. O que ele quer produzir é uma lista com o SSN e as notas. Também assumimos que, em sua aplicação, o instrutor não usa estrutura de dados, como matrizes, para armazenar as informações pessoais e os pontos do aluno. Se o instrutor decidir dar A's para aqueles que obtiveram a média da aula ou mais, e dar Bs para os outros, é melhor usar um analisador DOM em seu aplicativo. O motivo é que ele não tem como saber quanto é a média da turma antes que todo o documento seja processado. O que ele provavelmente precisa fazer em sua inscrição é o primeiro a analisar todos os pontos e calcule a média e, em seguida, examine o documento novamente e atribua a nota final a cada aluno comparando os pontos que ele ganhou com a média da turma. Se, no entanto, o instrutor adotar uma política de classificação que permita que os alunos com 90 pontos ou mais recebam A e os outros com B, provavelmente é melhor usar um analisador SAX. O motivo é que, para atribuir uma nota final a cada aluno, ele não precisa esperar que todo o documento seja processado. Ele pode atribuir uma nota imediatamente a um aluno assim que o analisador SAX ler a nota desse aluno. Na análise acima, assumimos que o instrutor não criou sua própria estrutura de dados. E se ele criar sua própria estrutura de dados, como uma matriz de cadeias para armazenar o SSN e uma matriz de números inteiros para armazenar os pontos? Nesse caso, Eu acho que o SAX é uma escolha melhor, antes que isso economizasse memória e tempo, além de fazer o trabalho. Bem, mais uma consideração neste exemplo. E se o que o instrutor deseja fazer não for imprimir uma lista, mas salvar o documento original de volta com a nota de cada aluno atualizada? Nesse caso, um analisador DOM deve ser uma escolha melhor, independentemente da política de classificação que ele esteja adotando. Ele não precisa criar nenhuma estrutura de dados própria. O que ele precisa fazer é primeiro modificar a árvore do DOM (ou seja, definir o valor para o nó 'grade') e depois salvar a árvore inteira modificada. Se ele optar por usar um analisador SAX em vez de um analisador DOM, nesse caso, ele precisará criar uma estrutura de dados quase tão complicada quanto uma árvore DOM antes que ele possa fazer o trabalho. ainda assim, faça o trabalho. Bem, mais uma consideração neste exemplo. E se o que o instrutor deseja fazer não for imprimir uma lista, mas salvar o documento original de volta com a nota de cada aluno atualizada? Nesse caso, um analisador DOM deve ser uma escolha melhor, independentemente da política de classificação que ele esteja adotando. Ele não precisa criar nenhuma estrutura de dados própria. O que ele precisa fazer é primeiro modificar a árvore do DOM (ou seja, definir o valor para o nó 'grade') e depois salvar a árvore inteira modificada. Se ele optar por usar um analisador SAX em vez de um analisador DOM, nesse caso, ele precisará criar uma estrutura de dados quase tão complicada quanto uma árvore DOM antes que ele possa fazer o trabalho. ainda assim, faça o trabalho. Bem, mais uma consideração neste exemplo. E se o que o instrutor deseja fazer não for imprimir uma lista, mas salvar o documento original de volta com a nota de cada aluno atualizada? Nesse caso, um analisador DOM deve ser uma escolha melhor, independentemente da política de classificação que ele esteja adotando. Ele não precisa criar nenhuma estrutura de dados própria. O que ele precisa fazer é primeiro modificar a árvore do DOM (ou seja, definir o valor para o nó 'grade') e depois salvar a árvore inteira modificada. Se ele optar por usar um analisador SAX em vez de um analisador DOM, nesse caso, ele precisará criar uma estrutura de dados quase tão complicada quanto uma árvore DOM antes que ele possa fazer o trabalho. mas para salvar o documento original de volta com a nota de cada aluno atualizada? Nesse caso, um analisador DOM deve ser uma escolha melhor, independentemente da política de classificação que ele esteja adotando. Ele não precisa criar nenhuma estrutura de dados própria. O que ele precisa fazer é primeiro modificar a árvore do DOM (ou seja, definir o valor para o nó 'grade') e depois salvar a árvore inteira modificada. Se ele optar por usar um analisador SAX em vez de um analisador DOM, nesse caso, ele precisará criar uma estrutura de dados quase tão complicada quanto uma árvore DOM antes que ele possa fazer o trabalho. mas para salvar o documento original de volta com a nota de cada aluno atualizada? Nesse caso, um analisador DOM deve ser uma escolha melhor, independentemente da política de classificação que ele esteja adotando. Ele não precisa criar nenhuma estrutura de dados própria. O que ele precisa fazer é primeiro modificar a árvore do DOM (ou seja, definir o valor para o nó 'grade') e depois salvar a árvore inteira modificada. Se ele optar por usar um analisador SAX em vez de um analisador DOM, nesse caso, ele precisará criar uma estrutura de dados quase tão complicada quanto uma árvore DOM antes que ele possa fazer o trabalho. nó) e salve a árvore inteira modificada. Se ele optar por usar um analisador SAX em vez de um analisador DOM, nesse caso, ele precisará criar uma estrutura de dados quase tão complicada quanto uma árvore DOM antes que ele possa fazer o trabalho. nó) e salve a árvore inteira modificada. Se ele optar por usar um analisador SAX em vez de um analisador DOM, nesse caso, ele precisará criar uma estrutura de dados quase tão complicada quanto uma árvore DOM antes que ele possa fazer o trabalho.
Um exemplo
Declaração do problema : escreva um programa Java para extrair todas as informações sobre círculos que são elementos em um determinado documento XML. Supomos que cada elemento do círculo tenha três elementos filhos (ou seja, x, ye raio), além de um atributo de cor. Um documento de amostra é fornecido abaixo:
<?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 com 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 com 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);
}
}
}