Я дам загальну відповідь на відповіді на питання та відповіді на це питання:
Відповідь на запитання
Для чого нам потрібен 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 і SAX парсером?
DOM-парсери та SAX-парсери працюють різними способами:
Аналізатор DOM створює структуру дерева в пам'яті з вхідного документа і потім чекає запитів від клієнта. Але SAX-аналізатор не створює жодної внутрішньої структури. Натомість він приймає вхід компонентів вхідного документа як події та повідомляє клієнту, що він читає, читаючи через вхідний документ. А
DOM-аналізатор завжди обслуговує клієнтську програму з усім документом, незалежно від того, скільки насправді потрібно клієнту. Але SAX-аналізатор обслуговує клієнтську програму завжди лише з фрагментами документа в будь-який момент.
- За допомогою аналізатора DOM, виклики методів у клієнтській програмі повинні бути явними та утворювати своєрідну ланцюжок. Але в SAX деякі певні методи (як правило, переосмислені коефіцієнтом) будуть викликатися автоматично (неявно) способом, який називається "зворотним викликом", коли відбуваються певні події. Ці методи не повинні викликати клієнт явно, хоча ми можемо їх чітко викликати.
Як ми вирішуємо, який парсер хороший?
В ідеалі гарний аналізатор повинен бути швидким (економічно ефективним), просторовим, багатим функціоналом і простим у використанні. Але насправді жоден з основних аналізаторів не має всіх цих особливостей одночасно. Наприклад, аналізатор DOM багатий функціоналом (тому що він створює дерево DOM в пам'яті і дозволяє отримувати доступ до будь-якої частини документа неодноразово і дозволяє змінювати дерево DOM), але це неефективний простір, коли документ величезний , і навчитися працювати з цим потрібно небагато часу. Однак, аналізатор SAX значно ефективніше простору у випадку великого вхідного документа (оскільки він не створює внутрішньої структури). Більше того, він працює швидше і його легше вивчити, ніж DOM Parser, оскільки його API справді простий. Але з точки зору функціональності, він надає менше функцій, що означає, що самі користувачі повинні дбати про більше, наприклад створення власних структур даних. До речі, що таке хороший аналізатор? Я думаю, що відповідь дійсно залежить від особливостей вашої заяви.
Які є реальні додатки, коли використання аналізатора SAX вигідніше, ніж використання аналізатора DOM і навпаки? Які звичайні програми для аналізатора DOM і для аналізатора SAX?
У наступних випадках використання аналізатора SAX вигідніше, ніж використання аналізатора DOM.
- Вхідний документ занадто великий для доступної пам'яті (насправді в цьому випадку SAX - ваш єдиний вибір)
- Ви можете обробити документ невеликими суміжними фрагментами введення. Вам не потрібен весь документ, перш ніж ви зможете зробити корисну роботу
- Ви просто хочете використовувати парсер для вилучення цікавої інформації, і всі ваші обчислення будуть повністю засновані на створених вами структурах даних. Насправді в більшості наших додатків ми створюємо власні структури даних, які зазвичай не такі складні, як дерево DOM. З цього сенсу, я думаю, шанс використання аналізатора DOM менший, ніж шанс використання аналізатора SAX.
У наступних випадках використання аналізатора DOM вигідніше, ніж використання аналізатора SAX.
- У вашій програмі потрібно одночасно отримувати доступ до широко відокремлених частин документа.
- Ваша програма, можливо, може використовувати внутрішню структуру даних, яка майже така ж складна, як і сам документ.
- Ваша заявка повинна неодноразово змінювати документ.
- Ваша програма повинна зберігати документ протягом значної кількості часу через багато дзвінків методів.
Приклад (Використовувати аналізатор DOM або аналізатор SAX?):
Припустимо, що у викладача є XML-документ, який містить усю особисту інформацію учнів, а також бали, які його студенти склали у своєму класі, і він тепер присвоює випускні оцінки студентам за допомогою програми. Що він хоче скласти, - це список із SSN та оцінками. Також ми припускаємо, що у своїй заяві інструктор не використовує такої структури даних, як масиви для зберігання особистої інформації студента та балів. Якщо викладач вирішить дати А тим, хто заробив середній клас або вище, а В дасть іншим, тоді він краще використовувати аналізатор DOM у своїй заявці. Причина полягає в тому, що він не може знати, скільки коштує середнє число класів, перш ніж весь документ буде оброблений. Що він, мабуть, повинен зробити у своїй заявці, спочатку перегляне всі студенти балів і обчисліть середнє, а потім ще раз перегляньте документ і призначте підсумкову оцінку кожному студенту, порівнявши отримані ним бали із середнім класом. Якщо, однак, викладач прийме таку політику оцінювання, що студентам, які отримали 90 балів або більше, присвоюється А, а іншим присвоєно B, тоді, ймовірно, він краще використовувати аналізатор 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);
}
}
}