मैं इस प्रश्न के लिए सामान्य प्रश्नोत्तर उत्तर दूंगा:
सवालों के जवाब
हमें XML पार्सर की आवश्यकता क्यों है?
हमें XML पार्सर की आवश्यकता है क्योंकि हम स्क्रैच से अपने एप्लिकेशन में सब कुछ नहीं करना चाहते हैं, और हमें कुछ बहुत ही निम्न-स्तरीय लेकिन हमारे लिए बहुत आवश्यक होने के लिए कुछ "हेल्पर" प्रोग्राम या लाइब्रेरी की आवश्यकता है। इन निम्न-स्तरीय लेकिन आवश्यक चीजों में अच्छी तरह से गठितता की जांच करना, इसके DTD या स्कीमा के खिलाफ दस्तावेज़ को मान्य करना (बस पार्सर्स को मान्य करने के लिए), चरित्र संदर्भ को हल करना, CDATA अनुभागों को समझना, और इसी तरह शामिल हैं। XML पार्सर सिर्फ ऐसे "हेल्पर" प्रोग्राम हैं और वे ये सभी काम करेंगे। XML पार्सर के साथ, हमें इन जटिलताओं के बहुत से परिरक्षित किया जाता है और हम पार्सर्स द्वारा लागू एपीआई के माध्यम से उच्च स्तर पर सिर्फ प्रोग्रामिंग पर ध्यान केंद्रित कर सकते हैं, और इस प्रकार प्रोग्रामिंग दक्षता प्राप्त कर सकते हैं।
कौन सा बेहतर है, SAX या DOM?
SAX और DOM पार्सर दोनों के अपने फायदे और नुकसान हैं। कौन सा बेहतर है, आपके आवेदन की विशेषताओं पर निर्भर होना चाहिए (कृपया नीचे कुछ प्रश्नों को देखें)।
कौन से पार्सर बेहतर गति, डोम या एसएएक्स पार्सर प्राप्त कर सकते हैं?
SAX पार्सर से बेहतर स्पीड मिल सकती है।
ट्री-आधारित API और ईवेंट-आधारित API में क्या अंतर है?
ट्री-आधारित API एक ट्री संरचना के आसपास केंद्रित है और इसलिए एक ट्री के घटकों (जो एक DOM दस्तावेज़ है) पर दस्तावेज़ इंटरफ़ेस, नोड इंटरफ़ेस, नोडलिस्ट इंटरफ़ेस, तत्व इंटरफ़ेस, Attr इंटरफ़ेस और इतने पर इंटरफेस प्रदान करता है। हालांकि, इसके विपरीत, एक घटना-आधारित एपीआई हैंडलर पर इंटरफेस प्रदान करता है। चार हैंडलर इंटरफेस, कंटेंटहैंडलर इंटरफ़ेस, DTDHandler इंटरफ़ेस, EntityResolver इंटरफ़ेस और ErrorHandler इंटरफ़ेस हैं।
DOM पार्सर और SAX पार्सर में क्या अंतर है?
DOM पार्सर और SAX पार्सर विभिन्न तरीकों से काम करते हैं:
DOM पार्सर इनपुट डॉक्यूमेंट से मेमोरी में ट्री स्ट्रक्चर बनाता है और फिर क्लाइंट से रिक्वेस्ट का इंतजार करता है। लेकिन एक एसएएक्स पार्सर किसी भी आंतरिक संरचना का निर्माण नहीं करता है। इसके बजाय, यह एक इनपुट दस्तावेज़ के घटकों की घटनाओं को घटनाओं के रूप में लेता है, और क्लाइंट को बताता है कि वह क्या पढ़ता है जैसा कि इनपुट दस्तावेज़ के माध्यम से पढ़ता है। ए
DOM पार्सर हमेशा पूरे दस्तावेज़ के साथ क्लाइंट एप्लिकेशन को सेवा देता है, चाहे वह वास्तव में क्लाइंट द्वारा कितनी ही आवश्यक हो। लेकिन एक SAX पार्सर क्लाइंट एप्लिकेशन को हमेशा किसी भी समय दस्तावेज़ के टुकड़ों के साथ कार्य करता है।
- DOM पार्सर के साथ, क्लाइंट एप्लिकेशन में विधि कॉल को स्पष्ट किया जाना चाहिए और एक प्रकार की श्रृंखला बनती है। लेकिन SAX के साथ, कुछ निश्चित विधियाँ (आमतौर पर cient द्वारा ओवरराइड की जाती हैं) को स्वचालित रूप से (अव्यवस्थित रूप से) एक तरह से लागू किया जाएगा, जिसे कुछ निश्चित घटनाओं के होने पर "कॉलबैक" कहा जाता है। इन तरीकों को ग्राहक द्वारा स्पष्ट रूप से नहीं बुलाया जाना चाहिए, हालांकि हम उन्हें स्पष्ट रूप से कह सकते हैं।
हम कैसे तय करते हैं कि कौन सा पार्सर अच्छा है?
आदर्श रूप से एक अच्छा पार्सर तेज (समय कुशल), अंतरिक्ष कुशल, कार्यक्षमता में समृद्ध और उपयोग में आसान होना चाहिए। लेकिन वास्तव में, मुख्य पार्सरों में से किसी के पास एक ही समय में ये सभी विशेषताएं नहीं हैं। उदाहरण के लिए, एक DOM पार्सर कार्यक्षमता में समृद्ध है (क्योंकि यह मेमोरी में DOM ट्री बनाता है और आपको दस्तावेज़ के किसी भी भाग को बार-बार एक्सेस करने की अनुमति देता है और आपको DOM ट्री को संशोधित करने की अनुमति देता है), लेकिन दस्तावेज़ के विशाल होने पर यह स्थान अक्षम है , और इसके साथ काम करने का तरीका सीखने में थोड़ा समय लगता है। SAX पार्सर, हालांकि, बड़े इनपुट दस्तावेज़ के मामले में अधिक स्थान कुशल है (क्योंकि यह कोई आंतरिक संरचना नहीं बनाता है)। क्या अधिक है, यह तेजी से चलता है और डोम पार्सर की तुलना में सीखना आसान है क्योंकि इसका एपीआई वास्तव में सरल है। लेकिन कार्यक्षमता के दृष्टिकोण से, यह कम कार्य प्रदान करता है जिसका अर्थ है कि उपयोगकर्ताओं को स्वयं का अधिक ध्यान रखना होगा, जैसे कि अपनी स्वयं की डेटा संरचनाएँ बनाना। वैसे, एक अच्छा पार्सर क्या है? मुझे लगता है कि उत्तर वास्तव में आपके आवेदन की विशेषताओं पर निर्भर करता है।
कुछ वास्तविक दुनिया अनुप्रयोग क्या हैं जहां SAX पार्सर का उपयोग DOM पार्सर और इसके विपरीत का उपयोग करने से अधिक फायदेमंद है? DOM पार्सर और SAX पार्सर के लिए सामान्य अनुप्रयोग क्या हैं?
निम्नलिखित मामलों में, एसएएक्स पार्सर का उपयोग डोम पार्सर का उपयोग करने की तुलना में फायदेमंद है।
- उपलब्ध स्मृति के लिए इनपुट दस्तावेज़ बहुत बड़ा है (वास्तव में इस मामले में एसएएक्स आपकी एकमात्र पसंद है)
- आप दस्तावेज़ को इनपुट के छोटे सन्निकट विखंडू में संसाधित कर सकते हैं। उपयोगी कार्य करने से पहले आपको संपूर्ण दस्तावेज़ की आवश्यकता नहीं है
- आप केवल ब्याज की जानकारी निकालने के लिए पार्सर का उपयोग करना चाहते हैं, और आपकी सभी गणना पूरी तरह से स्वयं द्वारा बनाई गई डेटा संरचनाओं पर आधारित होगी। वास्तव में हमारे अधिकांश अनुप्रयोगों में, हम अपने स्वयं के डेटा संरचनाएं बनाते हैं जो आमतौर पर DOM पेड़ के रूप में जटिल नहीं होते हैं। इस अर्थ से, मुझे लगता है, एक डोम पार्सर का उपयोग करने का मौका एक एसएएक्स पार्सर का उपयोग करने की तुलना में कम है।
निम्नलिखित मामलों में, DOM पार्सर का उपयोग SAX पार्सर का उपयोग करने की तुलना में लाभप्रद है।
- आपके एप्लिकेशन को एक ही समय में दस्तावेज़ के व्यापक रूप से अलग-अलग हिस्सों तक पहुंचने की आवश्यकता है।
- आपका एप्लिकेशन संभवतः आंतरिक डेटा संरचना का उपयोग कर सकता है जो दस्तावेज़ के रूप में लगभग उतना ही जटिल है।
- आपके एप्लिकेशन को दस्तावेज़ को बार-बार संशोधित करना होगा।
- आपके एप्लिकेशन को कई महत्वपूर्ण कॉल के माध्यम से दस्तावेज़ को महत्वपूर्ण समय के लिए संग्रहीत करना होगा।
उदाहरण (DOM पार्सर या SAX पार्सर का उपयोग करें?):
मान लें कि एक प्रशिक्षक के पास एक XML दस्तावेज है जिसमें छात्रों की सभी व्यक्तिगत जानकारी के साथ-साथ उनके छात्रों द्वारा उनकी कक्षा में बनाए गए अंक भी हैं, और वह अब एक आवेदन का उपयोग करके छात्रों के लिए अंतिम ग्रेड प्रदान कर रहा है। वह क्या उत्पादन करना चाहता है, एसएसएन और ग्रेड के साथ एक सूची है। इसके अलावा, हम मानते हैं कि उनके आवेदन में, प्रशिक्षक छात्र की व्यक्तिगत जानकारी और बिंदुओं को संग्रहीत करने के लिए सरणियों जैसे डेटा संरचना का उपयोग नहीं करता है। अगर प्रशिक्षक ए को उन लोगों को देने का फैसला करता है जो वर्ग औसत या उससे अधिक कमाते हैं, और दूसरों को बी देते हैं, तो वह अपने आवेदन में डोम पार्सर का उपयोग करना बेहतर होगा। कारण यह है कि उसके पास यह जानने का कोई तरीका नहीं है कि पूरे दस्तावेज के संसाधित होने से पहले कक्षा का औसत कितना है। शायद उसे अपने आवेदन में क्या करना है, सबसे पहले सभी छात्रों को देखना है अंक और औसत की गणना करें, और फिर दस्तावेज़ के माध्यम से फिर से देखें और प्रत्येक छात्र को वर्ग औसत से अर्जित अंकों की तुलना करके अंतिम ग्रेड प्रदान करें। यदि, हालांकि, प्रशिक्षक ऐसी ग्रेडिंग नीति अपनाता है कि जिन छात्रों को 90 अंक या उससे अधिक मिले, उन्हें ए और अन्य को बी के असाइन किया गया है, तो शायद वह एसएएक्स पार्सर का बेहतर उपयोग करेंगे। इसका कारण है, प्रत्येक छात्र को अंतिम ग्रेड देने के लिए, उसे पूरे दस्तावेज के संसाधित होने की प्रतीक्षा करने की आवश्यकता नहीं है। एसएएक्स पार्सर इस छात्र के ग्रेड को पढ़ता है, तो वह तुरंत एक छात्र को एक ग्रेड प्रदान कर सकता है। उपरोक्त विश्लेषण में, हमने मान लिया कि प्रशिक्षक ने स्वयं की कोई डेटा संरचना नहीं बनाई है। क्या होगा यदि वह SSN को संग्रहीत करने के लिए स्ट्रिंग की एक सरणी और पूर्णांक के एक अंक के रूप में अपनी खुद की डेटा संरचना बनाता है, फिर से अंक प्राप्त करने के लिए? इस मामले में, मुझे लगता है कि SAX एक बेहतर विकल्प है, इससे पहले कि यह मेमोरी और समय दोनों को बचा सकता है, फिर भी काम पूरा कर सकता है। खैर, इस उदाहरण पर एक और विचार। क्या होगा यदि प्रशिक्षक क्या करना चाहता है, सूची को प्रिंट नहीं करना है, बल्कि अद्यतन किए गए प्रत्येक छात्र के ग्रेड के साथ मूल दस्तावेज को वापस बचाना है? इस मामले में, एक DOM पार्सर एक बेहतर विकल्प होना चाहिए, चाहे वह कोई भी ग्रेडिंग नीति अपना रहा हो। उसे अपनी खुद की कोई डेटा संरचना बनाने की आवश्यकता नहीं है। उसे जो करना है, उसे पहले DOM ट्री (यानी, 'ग्रेड' नोड के लिए सेट मूल्य) को संशोधित करना है और फिर पूरे संशोधित पेड़ को बचाना है। यदि वह DOM पार्सर के बजाय SAX पार्सर का उपयोग करने का चयन करता है, तो इस मामले में उसे एक डेटा संरचना तैयार करनी होगी जो कि DOM ट्री के रूप में लगभग जटिल है, इससे पहले कि वह काम कर सके। अभी तक काम नहीं मिला। खैर, इस उदाहरण पर एक और विचार। क्या होगा यदि प्रशिक्षक क्या करना चाहता है, सूची को प्रिंट नहीं करना है, बल्कि अद्यतन किए गए प्रत्येक छात्र के ग्रेड के साथ मूल दस्तावेज को वापस बचाना है? इस मामले में, एक DOM पार्सर एक बेहतर विकल्प होना चाहिए, चाहे वह कोई भी ग्रेडिंग नीति अपना रहा हो। उसे अपनी खुद की कोई डेटा संरचना बनाने की आवश्यकता नहीं है। उसे जो करना है, उसे पहले DOM ट्री (यानी, 'ग्रेड' नोड के लिए सेट मूल्य) को संशोधित करना है और फिर पूरे संशोधित पेड़ को बचाना है। यदि वह DOM पार्सर के बजाय SAX पार्सर का उपयोग करने का विकल्प चुनता है, तो इस मामले में उसे एक डेटा संरचना तैयार करनी होगी जो कि DOM ट्री के रूप में लगभग जटिल है इससे पहले कि वह काम कर सके। अभी तक काम नहीं मिला। खैर, इस उदाहरण पर एक और विचार। क्या होगा यदि प्रशिक्षक क्या करना चाहता है, सूची को प्रिंट नहीं करना है, बल्कि अद्यतन किए गए प्रत्येक छात्र के ग्रेड के साथ मूल दस्तावेज को वापस बचाना है? इस मामले में, एक DOM पार्सर एक बेहतर विकल्प होना चाहिए, चाहे वह कोई भी ग्रेडिंग नीति अपना रहा हो। उसे अपनी खुद की कोई डेटा संरचना बनाने की आवश्यकता नहीं है। उसे जो करना है, उसे पहले DOM ट्री (यानी, 'ग्रेड' नोड के लिए सेट मूल्य) को संशोधित करना है और फिर पूरे संशोधित पेड़ को बचाना है। यदि वह DOM पार्सर के बजाय SAX पार्सर का उपयोग करने का विकल्प चुनता है, तो इस मामले में उसे एक डेटा संरचना तैयार करनी होगी जो कि DOM ट्री के रूप में लगभग जटिल है इससे पहले कि वह काम कर सके। लेकिन अद्यतन किए गए प्रत्येक छात्र के ग्रेड के साथ मूल दस्तावेज को वापस बचाने के लिए? इस मामले में, एक DOM पार्सर एक बेहतर विकल्प होना चाहिए, चाहे वह कोई भी ग्रेडिंग नीति अपना रहा हो। उसे अपनी खुद की कोई डेटा संरचना बनाने की आवश्यकता नहीं है। उसे जो करना है, उसे पहले DOM ट्री (यानी, 'ग्रेड' नोड के लिए सेट मूल्य) को संशोधित करना है और फिर पूरे संशोधित पेड़ को बचाना है। यदि वह DOM पार्सर के बजाय SAX पार्सर का उपयोग करने का विकल्प चुनता है, तो इस मामले में उसे एक डेटा संरचना तैयार करनी होगी जो कि DOM ट्री के रूप में लगभग जटिल है इससे पहले कि वह काम कर सके। लेकिन अद्यतन किए गए प्रत्येक छात्र के ग्रेड के साथ मूल दस्तावेज को वापस बचाने के लिए? इस मामले में, एक DOM पार्सर एक बेहतर विकल्प होना चाहिए, चाहे वह कोई भी ग्रेडिंग नीति अपना रहा हो। उसे अपनी खुद की कोई डेटा संरचना बनाने की आवश्यकता नहीं है। उसे जो करना है, उसे पहले DOM ट्री (यानी, 'ग्रेड' नोड के लिए सेट मूल्य) को संशोधित करना है और फिर पूरे संशोधित पेड़ को बचाना है। यदि वह DOM पार्सर के बजाय SAX पार्सर का उपयोग करने का विकल्प चुनता है, तो इस मामले में उसे एक डेटा संरचना तैयार करनी होगी जो कि DOM ट्री के रूप में लगभग जटिल है इससे पहले कि वह काम कर सके। नोड) और फिर पूरे संशोधित पेड़ को बचाएं। यदि वह DOM पार्सर के बजाय SAX पार्सर का उपयोग करने का विकल्प चुनता है, तो इस मामले में उसे एक डेटा संरचना तैयार करनी होगी जो कि DOM ट्री के रूप में लगभग जटिल है इससे पहले कि वह काम कर सके। नोड) और फिर पूरे संशोधित पेड़ को बचाएं। यदि वह DOM पार्सर के बजाय SAX पार्सर का उपयोग करने का विकल्प चुनता है, तो इस मामले में उसे एक डेटा संरचना तैयार करनी होगी जो कि DOM ट्री के रूप में लगभग जटिल है इससे पहले कि वह काम कर सके।
एक उदाहरण
समस्या कथन : किसी दिए गए 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>
डॉम्परर के साथ कार्यक्रम
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);
}
}
}