Я дам общий ответ на вопросы и ответы на этот вопрос:
Ответ на вопросы
Зачем нам нужен парсер XML?
Нам нужен синтаксический анализатор XML, потому что мы не хотим делать все в нашем приложении с нуля, и нам нужны некоторые «вспомогательные» программы или библиотеки для выполнения чего-то очень низкого уровня, но очень необходимого для нас. Эти низкоуровневые, но необходимые вещи включают проверку правильности формы, проверку документа по его DTD или схеме (только для проверки парсеров), разрешение ссылок на символы, понимание разделов CDATA и так далее. XML-парсеры - просто такие «вспомогательные» программы, и они будут выполнять все эти работы. С парсером XML мы защищены от многих этих сложностей, и мы могли бы сосредоточиться на простом программировании на высоком уровне через API, реализованный синтаксическими анализаторами, и таким образом повысить эффективность программирования.
Какой из них лучше, SAX или DOM?
Как SAX, так и DOM-парсер имеют свои преимущества и недостатки. Какой из них лучше, зависит от характеристик вашего приложения (см. Некоторые вопросы ниже).
Какой парсер может получить лучшую скорость, DOM или SAX парсеры?
SAX-парсер может получить лучшую скорость.
В чем разница между API на основе дерева и API на основе событий?
API на основе дерева сосредоточен вокруг древовидной структуры и, следовательно, предоставляет интерфейсы для компонентов дерева (который является документом DOM), таких как интерфейс документа, интерфейс узла, интерфейс NodeList, интерфейс элемента, интерфейс Attr и так далее. Однако API на основе событий предоставляет интерфейсы для обработчиков. Существует четыре интерфейса обработчиков, интерфейс ContentHandler, интерфейс DTDHandler, интерфейс EntityResolver и интерфейс ErrorHandler.
В чем разница между DOM Parser и SAX Parser?
Парсеры DOM и SAX работают по-разному:
Анализатор DOM создает древовидную структуру в памяти из входного документа и затем ожидает запросы от клиента. Но парсер SAX не создает никакой внутренней структуры. Вместо этого он принимает в качестве событий компоненты входного документа и сообщает клиенту, что он читает, когда он читает входной документ.
Парсер DOM всегда предоставляет клиентскому приложению весь документ, независимо от того, сколько на самом деле нужно клиенту. Но парсер SAX обслуживает клиентское приложение всегда только с частями документа в любой момент времени.
- При использовании синтаксического анализатора DOM вызовы методов в клиентском приложении должны быть явными и образовывать некую цепочку. Но с SAX некоторые определенные методы (обычно переопределяемые cient) будут вызываться автоматически (неявно) способом, который называется «обратным вызовом», когда происходят некоторые определенные события. Эти методы не должны вызываться явно клиентом, хотя мы могли бы вызывать их явно.
Как мы решаем, какой парсер хорош?
В идеале хороший синтаксический анализатор должен быть быстрым (экономичным по времени), компактным, функциональным и простым в использовании. Но в действительности ни один из основных анализаторов не обладает всеми этими функциями одновременно. Например, синтаксический анализатор DOM обладает широкими функциональными возможностями (поскольку он создает дерево DOM в памяти и позволяет многократно обращаться к любой части документа, а также позволяет изменять дерево DOM), но он неэффективен в случае большого размера документа. и это займет немного времени, чтобы научиться работать с ним. Парсер SAX, однако, намного более экономит место в случае большого входного документа (потому что он не создает внутренней структуры). Более того, он работает быстрее и его легче изучать, чем DOM Parser, потому что его API действительно прост. Но с точки зрения функциональности, он предоставляет меньше функций, которые означают, что сами пользователи должны заботиться о большем, например, создавать свои собственные структуры данных. Кстати, что такое хороший парсер? Я думаю, что ответ действительно зависит от характеристик вашего приложения.
В каких реальных приложениях SAX-парсер выгоднее, чем DOM-парсер и наоборот? Каковы обычные приложения для парсера DOM и парсера SAX?
В следующих случаях использование парсера SAX выгоднее, чем парсера DOM.
- Входной документ слишком велик для доступной памяти (фактически в этом случае SAX - ваш единственный выбор)
- Вы можете обрабатывать документ небольшими непрерывными порциями ввода. Вам не нужен весь документ, прежде чем вы сможете сделать полезную работу
- Вы просто хотите использовать анализатор для извлечения интересующей информации, и все ваши вычисления будут полностью основаны на структурах данных, созданных вами. На самом деле в большинстве наших приложений мы создаем собственные структуры данных, которые обычно не так сложны, как дерево DOM. В этом смысле, я думаю, вероятность использования DOM-парсера меньше, чем у SAX-парсера.
В следующих случаях использование парсера DOM выгоднее, чем парсера SAX.
- Ваше приложение должно иметь доступ к отдельным частям документа одновременно.
- Ваше приложение может использовать внутреннюю структуру данных, которая почти так же сложна, как и сам документ.
- Ваша заявка должна повторно изменить документ.
- Ваше приложение должно хранить документ в течение значительного периода времени посредством множества вызовов методов.
Пример (Использовать анализатор DOM или SAX?):
Предположим, что у инструктора есть XML-документ, содержащий всю личную информацию учеников, а также баллы, которые его ученики сделали в своем классе, и теперь он назначает ученикам итоговые оценки с помощью приложения. То, что он хочет произвести, является списком с SSN и оценками. Также мы предполагаем, что в своем приложении инструктор не использует структуру данных, такую как массивы, для хранения личной информации ученика и баллов. Если инструктор решит дать A тем, кто получил средний балл или выше, а B другим, тогда ему лучше использовать анализатор DOM в своем приложении. Причина в том, что он не может узнать, сколько в среднем по классу, до обработки всего документа. Что он, вероятно, должен сделать в своем заявлении, это сначала просмотреть все студенты баллы и вычислите среднее значение, а затем снова просмотрите документ и назначьте итоговую оценку каждому ученику, сравнив баллы, которые он заработал, со средним в классе. Однако, если преподаватель принимает такую политику оценки, что ученикам, набравшим 90 или более баллов, присваиваются баллы А, а другим присваиваются баллы Б, тогда, вероятно, ему лучше использовать синтаксический анализатор SAX. Причина в том, что для того, чтобы назначить каждому ученику итоговую оценку, ему не нужно ждать обработки всего документа. Он может сразу назначить оценку студенту, когда парсер SAX прочитает оценку этого студента. В приведенном выше анализе мы предположили, что инструктор не создал собственную структуру данных. Что если он создаст свою собственную структуру данных, такую как массив строк для хранения SSN и массив целых чисел для хранения точек? В таком случае, Я думаю, что SAX - лучший выбор, прежде чем он мог бы сэкономить как память, так и время, но выполнить работу. Ну, еще одно соображение на этом примере. Что если преподаватель хочет не распечатать список, а сохранить исходный документ с обновленной оценкой каждого учащегося? В этом случае анализатор DOM должен быть лучшим выбором, независимо от того, какую политику оценки он принимает. Ему не нужно создавать какую-либо собственную структуру данных. Ему нужно сначала изменить дерево DOM (т.е. установить значение для узла 'grade'), а затем сохранить все измененное дерево. Если он решит использовать парсер SAX вместо парсера DOM, то в этом случае он должен создать структуру данных, которая почти так же сложна, как дерево DOM, прежде чем он сможет выполнить свою работу. все же сделай работу. Ну, еще одно соображение на этом примере. Что если преподаватель хочет не распечатать список, а сохранить исходный документ с обновленной оценкой каждого учащегося? В этом случае анализатор DOM должен быть лучшим выбором, независимо от того, какую политику оценки он принимает. Ему не нужно создавать какую-либо собственную структуру данных. Ему нужно сначала изменить дерево DOM (т.е. установить значение для узла 'grade'), а затем сохранить все измененное дерево. Если он решит использовать парсер SAX вместо парсера DOM, то в этом случае он должен создать структуру данных, которая почти так же сложна, как дерево DOM, прежде чем он сможет выполнить свою работу. все же сделай работу. Ну, еще одно соображение на этом примере. Что если преподаватель хочет не распечатать список, а сохранить исходный документ с обновленной оценкой каждого учащегося? В этом случае анализатор DOM должен быть лучшим выбором, независимо от того, какую политику оценки он принимает. Ему не нужно создавать какую-либо собственную структуру данных. Ему нужно сначала изменить дерево DOM (т.е. установить значение для узла 'grade'), а затем сохранить все измененное дерево. Если он решит использовать парсер SAX вместо парсера DOM, то в этом случае он должен создать структуру данных, которая почти так же сложна, как дерево DOM, прежде чем он сможет выполнить свою работу. но сохранить исходный документ обратно с обновленной оценкой каждого студента? В этом случае анализатор DOM должен быть лучшим выбором, независимо от того, какую политику оценки он принимает. Ему не нужно создавать какую-либо собственную структуру данных. Ему нужно сначала изменить дерево DOM (т.е. установить значение для узла 'grade'), а затем сохранить все измененное дерево. Если он решит использовать парсер SAX вместо парсера DOM, то в этом случае он должен создать структуру данных, которая почти так же сложна, как дерево DOM, прежде чем он сможет выполнить свою работу. но сохранить исходный документ обратно с обновленной оценкой каждого студента? В этом случае анализатор DOM должен быть лучшим выбором, независимо от того, какую политику оценки он принимает. Ему не нужно создавать какую-либо собственную структуру данных. Ему нужно сначала изменить дерево DOM (т.е. установить значение для узла 'grade'), а затем сохранить все измененное дерево. Если он решит использовать парсер SAX вместо парсера DOM, то в этом случае он должен создать структуру данных, которая почти так же сложна, как дерево DOM, прежде чем он сможет выполнить свою работу. узел), а затем сохранить все измененное дерево. Если он решит использовать парсер SAX вместо парсера DOM, то в этом случае он должен создать структуру данных, которая почти так же сложна, как дерево DOM, прежде чем он сможет выполнить свою работу. узел), а затем сохранить все измененное дерево. Если он решит использовать парсер SAX вместо парсера DOM, то в этом случае он должен создать структуру данных, которая почти так же сложна, как дерево DOM, прежде чем он сможет выполнить свою работу.
Пример
Постановка проблемы : Напишите программу на Java для извлечения всей информации о кругах, которые являются элементами в данном документе XML. Мы предполагаем, что каждый элемент круга имеет три дочерних элемента (то есть x, y и радиус), а также атрибут цвета. Пример документа приведен ниже:
<?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>
Программа с 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);}
}
}
Программа с 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);
}
}
}