HTML / XML को पार्स करने के लिए regex का उपयोग करना क्यों संभव नहीं है: आम आदमी की शर्तों में एक औपचारिक स्पष्टीकरण


117

एसओ का कोई दिन नहीं है जो नियमित एक्सप्रेशंस के साथ पार्सिंग (एक्स) एचटीएमएल या एक्सएमएल के बारे में सवाल पूछे बिना गुजरता है।

हालांकि इस कार्य के लिए रीजैक्स की गैर-व्यवहार्यता को प्रदर्शित करने वाले या अवधारणा का प्रतिनिधित्व करने के लिए अभिव्यक्ति के संग्रह के साथ प्रदर्शन करना अपेक्षाकृत आसान है , फिर भी मुझे एसओ पर औपचारिक स्पष्टीकरण नहीं मिला कि यह आम आदमी के लिए क्यों संभव नहीं है। शर्तों।

इस साइट पर अब तक मिले एकमात्र औपचारिक स्पष्टीकरण शायद बेहद सटीक हैं, लेकिन स्व-सिखाया प्रोग्रामर के लिए भी काफी गूढ़ हैं:

दोष यह है कि HTML एक चॉम्स्की टाइप 2 व्याकरण (संदर्भ मुक्त व्याकरण) है और RegEx एक चॉम्स्की टाइप 3 व्याकरण (नियमित अभिव्यक्ति) है

या:

नियमित अभिव्यक्ति केवल नियमित भाषाओं से मेल खा सकती है लेकिन HTML एक संदर्भ-मुक्त भाषा है।

या:

एक परिमित ऑटोमेटन (जो एक नियमित अभिव्यक्ति अंतर्निहित डेटा संरचना है) में उस राज्य के अलावा मेमोरी नहीं है और यदि आपके पास मनमाने ढंग से गहरे घोंसले के शिकार हैं, तो आपको एक मनमाने ढंग से बड़े ऑटोमेटोन की आवश्यकता होती है, जो एक परिमित ऑटोमेटन की धारणा से टकराता है।

या:

नियमित भाषाओं के लिए पम्पिंग लेम्मा यही कारण है कि आप ऐसा नहीं कर सकते।

[उचित होने के लिए: विकिपीडिया पृष्ठों के लिए उपरोक्त व्याख्या लिंक के अधिकांश, लेकिन ये स्वयं के उत्तरों की तुलना में समझने में बहुत आसान नहीं हैं]।

तो मेरा प्रश्न है: क्या कोई व्यक्ति आम तौर पर ऊपर दिए गए औपचारिक स्पष्टीकरण की शर्तों में अनुवाद प्रदान कर सकता है, इसलिए पार्सिंग (एक्स) HTML / XML के लिए regex का उपयोग करना संभव नहीं है?

EDIT: पहला उत्तर पढ़ने के बाद मैंने सोचा कि मुझे स्पष्ट करना चाहिए: मैं एक "अनुवाद" की तलाश कर रहा हूं जो संक्षेप में उन अवधारणाओं की व्याख्या करता है जो अनुवाद करने की कोशिश करता है: उत्तर के अंत में, पाठक को एक मोटा विचार होना चाहिए - उदाहरण के लिए - किस "नियमित भाषा" और "संदर्भ-मुक्त व्याकरण" का अर्थ ...


19
इस तथ्य से अवगत रहें कि कंप्यूटर विज्ञान के संदर्भ में, "नियमित अभिव्यक्ति" आधुनिक दिन "रेगेक्स कार्यान्वयन" (उपकरण / एपीआई का आप एक प्रोग्रामिंग भाषा में उपयोग करते हैं) से बहुत भिन्न हैं। उत्तरार्द्ध ने उन चीजों को "याद" किया जो वे सामना कर चुके हैं और यहां तक ​​कि पुनरावर्ती रूप से परिभाषित (उप) पैटर्न से मेल खा सकते हैं, जिससे वे सैद्धांतिक "नियमित अभिव्यक्तियों" की तुलना में अधिक मैच / पार्स / पहचान कर सकते हैं।
बार्ट कियर्स

1
@ बर्ट: यह वास्तव में "रेगुलर एक्सप्रेशन" शब्द का दुरुपयोग करने वाली भाषाओं पर लागू होता है। पॉसिक्स ईआरई पूरी तरह से नियमित है।
R .. GitHub STOP HELPING ICE

2
@R .., इसलिए, आप POSIX को "आधुनिक दिन कार्यान्वयन" कहते हैं: पी। हालांकि सभी गंभीरता में: हाँ, आप सही हैं जो वास्तव में नियमित हैं। मुझे कहना चाहिए "... आधुनिक दिन regex कार्यान्वयन के कई ..." या "... PCRE regex कार्यान्वयन ..."
बार्ट कीर्स जुएल

4
मेरे पास एक कठिन समय है कि प्रोग्रामिंग भाषाओं को गंभीरता से लेते हुए कि अज्ञानी प्रोग्रामर को खुद की मार्केटिंग के लिए मौलिक रूप से कठोर भाषा का दुरुपयोग करें ...
R .. GitHub STOP HELPING ICE

3
@ आर .., यह दुर्भाग्यपूर्ण है कि पीसीआरई-कार्यान्वयन को "नियमित अभिव्यक्ति" के रूप में संदर्भित किया जाता है, लेकिन भाषा को गंभीर नहीं लेते हुए इसे एक कदम बहुत दूर ले जा रहा है, आईएमओ। मेरा मतलब है, क्या आप पर्ल, जावा, पायथन, रूबी, जावास्क्रिप्ट, .NET आदि को नहीं ले रहे हैं, क्योंकि यह गंभीर नहीं है?
बार्ट कियर्स

जवाबों:


117

इस पर ध्यान लगाओ:

एक परिमित ऑटोमेटन (जो एक नियमित अभिव्यक्ति अंतर्निहित डेटा संरचना है) में उस राज्य के अलावा मेमोरी नहीं है और यदि आपके पास मनमाने ढंग से गहरे घोंसले के शिकार हैं, तो आपको एक मनमाने ढंग से बड़े ऑटोमेटोन की आवश्यकता होती है, जो एक परिमित ऑटोमेटन की धारणा से टकराता है।

नियमित अभिव्यक्तियों परिभाषा इस तथ्य के बराबर है कि एक स्ट्रिंग पैटर्न से मेल खाती है या नहीं इसका परीक्षण एक परिमित ऑटोमेटन (प्रत्येक पैटर्न के लिए एक अलग ऑटोमेटन) द्वारा किया जा सकता है। एक परिमित ऑटोमोटन की कोई स्मृति नहीं है - कोई स्टैक नहीं, कोई ढेर नहीं, पर स्क्रिबल करने के लिए कोई अनंत टेप नहीं। सभी के पास आंतरिक राज्यों की एक परिमित संख्या है, जिनमें से प्रत्येक को परीक्षण किए जा रहे स्ट्रिंग से इनपुट की एक इकाई पढ़ सकते हैं, और इसका उपयोग यह तय करने के लिए कर सकते हैं कि किस राज्य को आगे बढ़ना है। विशेष मामलों के रूप में, इसकी दो समाप्ति अवस्थाएँ हैं: "हाँ, वह मिलान", और "नहीं, वह मेल नहीं खाता"।

दूसरी ओर, HTML में ऐसी संरचनाएँ हैं जो मनमाने ढंग से गहरे घोंसले बना सकती हैं। यह निर्धारित करने के लिए कि कोई फ़ाइल HTML वैध है या नहीं, आपको यह जांचने की आवश्यकता है कि सभी समापन टैग पिछले उद्घाटन टैग से मेल खाते हैं। इसे समझने के लिए, आपको यह जानना होगा कि कौन सा तत्व बंद किया जा रहा है। बिना किसी मतलब के "याद" कि आपने कौन से शुरुआती टैग देखे हैं, कोई मौका नहीं।

हालांकि ध्यान दें कि अधिकांश "रेगेक्स" पुस्तकालय वास्तव में नियमित अभिव्यक्तियों की सख्त परिभाषा से अधिक की अनुमति देते हैं। यदि वे बैक-रेफरेंस का मिलान कर सकते हैं, तो वे नियमित भाषा से आगे निकल गए हैं। तो इसका कारण यह है कि आपको HTML पर रेगेक्स लाइब्रेरी का उपयोग नहीं करना चाहिए, यह इस तथ्य से थोड़ा अधिक जटिल है कि HTML नियमित नहीं है।


यहाँ परिमित राज्य ऑटोमेटा की भी अच्छी व्याख्या है: youtube.com/watch?v=vhiiia1_hC4
GDP2

55

तथ्य यह है कि HTML एक नियमित भाषा का प्रतिनिधित्व नहीं करता है एक लाल हेरिंग है। नियमित अभिव्यक्ति और नियमित भाषाएं एक जैसी लगती हैं, लेकिन नहीं हैं - वे एक ही मूल साझा नहीं करती हैं, लेकिन शैक्षणिक "नियमित भाषाओं" और इंजनों की वर्तमान मिलान शक्ति के बीच एक उल्लेखनीय दूरी है। वास्तव में, लगभग सभी आधुनिक नियमित अभिव्यक्ति इंजन गैर-नियमित सुविधाओं का समर्थन करते हैं - एक सरल उदाहरण है (.*)\1। जो वर्णों के दोहराए गए क्रम से मेल करने के लिए बैकरेफ़रिंग का उपयोग करता है - उदाहरण के लिए 123123, या bonbon। पुनरावर्ती / संतुलित संरचनाओं के मेल से ये और भी मज़ेदार हो जाते हैं।

लैरी वॉल के एक उद्धरण में विकिपीडिया इसे अच्छी तरह से प्रस्तुत करता है :

'रेगुलर एक्सप्रेशंस' [...] केवल वास्तविक रेगुलर एक्सप्रेशंस से थोड़े संबंधित हैं। फिर भी, शब्द हमारे पैटर्न मिलान इंजन की क्षमताओं के साथ विकसित हुआ है, इसलिए मैं यहां भाषाई आवश्यकता से लड़ने की कोशिश नहीं कर रहा हूं। हालांकि, मैं आमतौर पर उन्हें "रेगेक्स" (या "रेगेक्सेन" कहता हूं, जब मैं एक एंग्लो-सैक्सन मूड में हूं)।

"नियमित अभिव्यक्ति केवल नियमित भाषाओं से मेल खा सकती है", जैसा कि आप देख सकते हैं, एक सामान्य रूप से उल्लिखित गिरावट से अधिक कुछ नहीं है।

तो, फिर क्यों नहीं?

नियमित अभिव्यक्ति के साथ HTML से मेल न खाने का एक अच्छा कारण यह है कि "सिर्फ इसलिए कि आप का मतलब यह नहीं होना चाहिए कि आप"। जबकि संभव हो सकता है - नौकरी के लिए बस बेहतर उपकरण हैं । मानते हुए:

  • मान्य HTML कठिन / अधिक जटिल है जितना आप सोच सकते हैं।
  • "वैध" HTML के कई प्रकार हैं - HTML में क्या मान्य है, उदाहरण के लिए, XHTML में मान्य नहीं है।
  • इंटरनेट पर पाया जाने वाला अधिकांश मुफ्त-फॉर्म HTML वैसे भी मान्य नहीं है । HTML लाइब्रेरी इनसे निपटने का एक अच्छा काम करते हैं, और इनमें से कई सामान्य मामलों के लिए परीक्षण किया गया।
  • बहुत बार यह डेटा के एक हिस्से को पूरी तरह से पार्स किए बिना मैच करना असंभव है। उदाहरण के लिए, आप सभी शीर्षकों की तलाश में हो सकते हैं, और एक टिप्पणी या एक स्ट्रिंग शाब्दिक के अंदर मिलान कर सकते हैं। <h1>.*?</h1>मुख्य शीर्षक खोजने में एक साहसिक प्रयास हो सकता है, लेकिन यह मिल सकता है:

    <!-- <h1>not the title!</h1> -->

    या और भी:

    <script>
    var s = "Certainly <h1>not the title!</h1>";
    </script>

अंतिम बिंदु सबसे महत्वपूर्ण है:

  • एक समर्पित HTML पार्सर का उपयोग करना किसी भी regex से बेहतर है, जिसके साथ आप आ सकते हैं। बहुत बार, XPath आपके द्वारा आवश्यक डेटा को खोजने के लिए एक बेहतर अभिव्यंजक तरीका की अनुमति देता है, और HTML पार्सर का उपयोग करना अधिकांश लोगों को महसूस करने की तुलना में बहुत आसान है

विषय का एक अच्छा सारांश, और रेगेक्स और HTML को मिलाते समय एक महत्वपूर्ण टिप्पणी उपयुक्त हो सकती है, जेफ एटवुड के ब्लॉग में पाया जा सकता है: पार्सिंग एचटीएमएल द केथुलु वे

HTML को पार्स करने के लिए एक नियमित अभिव्यक्ति का उपयोग करना कब बेहतर है?

ज्यादातर मामलों में, DOM संरचना पर XPath का उपयोग करना बेहतर होता है जो एक पुस्तकालय आपको दे सकता है। फिर भी, लोकप्रिय राय के खिलाफ, कुछ मामले हैं जब मैं जोर से regex का उपयोग करने की सलाह दूंगा और न कि एक पार्सर लाइब्रेरी:

इनमें से कुछ शर्तों को देखते हुए:

  • जब आपको अपनी HTML फ़ाइलों के एक बार अपडेट की आवश्यकता होती है, और आपको पता है कि संरचना सुसंगत है।
  • जब आपके पास HTML का बहुत छोटा स्निपेट हो।
  • जब आप एक HTML फ़ाइल के साथ काम नहीं कर रहे हैं, लेकिन एक समान टेम्प्लेटिंग इंजन (उस मामले में एक पार्सर खोजने के लिए बहुत मुश्किल हो सकता है)।
  • जब आप HTML के कुछ हिस्सों को बदलना चाहते हैं, लेकिन यह सब नहीं - मेरी जानकारी के लिए एक पार्सर, इस अनुरोध का उत्तर नहीं दे सकता है: यह पूरे दस्तावेज़ को पार्स कर देगा, और एक संपूर्ण दस्तावेज़ को सहेजेगा, उन हिस्सों को बदलना जिन्हें आप कभी बदलना नहीं चाहते थे।

4
यह एक बहुत ही स्पष्ट और अच्छी तरह से लिखा गया टुकड़ा है जब HTML को पार्स करने के लिए रेगेक्स का उपयोग नहीं किया जाता है, लेकिन यह शायद ही मेरे सवाल का जवाब है। क्या मैं आपको सुझाव दूंगा कि आप इसे इस प्रश्न की जगह ले जाएं? मुझे लगता है कि यह आपको और अधिक प्रतिष्ठा दिलवाएगा लेकिन - सबसे ऊपर - मुझे लगता है कि यह एक ऐसी जगह होगी जहां भविष्य के आगंतुक इसे और अधिक प्रासंगिक पाएंगे (मेरे प्रश्न के लिए @Bart Kiers द्वारा एक टिप्पणी है जो आगंतुकों को "अतिरिक्त शक्ति" की याद दिलाती है। आधुनिक रेगेक्स इंजनों का)।
मैक

1
@ एमएसी - बहुत बहुत धन्यवाद। वास्तव में, मैंने इसे कुछ सोचा था। मुझे पता है कि मैंने आपके प्रश्न का उत्तर नहीं दिया है, लेकिन मुझे नहीं लगता कि प्रश्न मूल रूप से सही है - आप गलत कारण बताने के लिए कहते हैं ... आपके पास एक अच्छा विचार है, शायद दूसरा प्रश्न अधिक उपयुक्त है ...
कोबी

19

क्योंकि HTML में असीमित घोंसले के शिकार हो सकते हैं <tags><inside><tags and="<things><that><look></like></tags>"></inside></each></other>और regex वास्तव में इसका सामना नहीं कर सकता है क्योंकि यह एक इतिहास को ट्रैक नहीं कर सकता है कि इसमें क्या उतरा है और इससे बाहर आया।

एक साधारण निर्माण जो कठिनाई को दर्शाता है:

<body><div id="foo">Hi there!  <div id="bar">Bye!</div></div></body>

सामान्यीकृत रेगेक्स-आधारित निष्कर्षण दिनचर्या के 99.9% मुझे divआईडी के साथ सब कुछ सही ढंग से देने में असमर्थ होंगे foo, क्योंकि वे उस div के लिए समापन टैग से div के लिए समापन टैग नहीं बता सकते हैं bar। ऐसा इसलिए है क्योंकि उनके पास यह कहने का कोई तरीका नहीं है कि "ठीक है, मैं अब दो डिवीजनों में से दूसरे में उतर गया हूं, इसलिए मैं जो अगला तलाक देखता हूं वह मुझे एक बार वापस लाता है, और उसके बाद वाला पहला के लिए करीब टैग है" । प्रोग्रामर आम तौर पर विशिष्ट स्थिति के लिए विशेष-केस रेग्जेस को तैयार करके प्रतिक्रिया देते हैं, जो तब और अधिक टैग के रूप में अंदर से शुरू होते ही टूट जाते हैं fooऔर समय और निराशा में जबरदस्त लागत पर अनसेंड करना पड़ता है। यही कारण है कि लोग पूरी बात को लेकर पागल हो जाते हैं।


1
उत्तर की सराहना करें, लेकिन मेरा सवाल यह नहीं है कि "मैं रेगेक्स का उपयोग क्यों नहीं कर सकता ..."। मेरा प्रश्न मेरे द्वारा प्रदान की गई औपचारिक व्याख्याओं का "अनुवाद" करने के बारे में है! :)
मैक

5
यह कुछ अर्थों में उन सभी का अनुवाद है, सबसे अधिक "नियमित अभिव्यक्ति केवल नियमित भाषाओं से मेल खा सकती है लेकिन HTML एक संदर्भ-मुक्त भाषा है" और परिमित ऑटोमेटा के बारे में। यह वास्तव में सभी एक ही कारण है।
इनासुस चियाक्रूरो

क्षमा करें, हो सकता है कि मैं अपने प्रश्न में स्पष्ट न हो (इसमें सुधार के लिए सुझाव स्वागत योग्य हैं!)। लेकिन मैं एक ऐसे उत्तर की तलाश कर रहा हूं जो "अनुवाद" भी समझाए। आपका उत्तर या तो 'नियमित भाषा' या 'संदर्भ-मुक्त भाषा' अवधारणाओं को स्पष्ट नहीं करता है ...
मैक

5
उन शब्दों की व्याख्या करना केवल शब्दजाल जितना ही तकनीकी होगा, और वास्तविक अर्थ से एक व्याकुलता कि सभी सटीक भाषा मिल रही है, जो कि मैंने पोस्ट की है।
इयानस चियाक्रूरो

4
<(\w+)(?:\s+\w+="[^"]*")*>(?R)*</\1>|[\w\s!']+आपके कोड नमूने से मेल खाता है।
कोबी

9

एक नियमित भाषा एक भाषा है जिसे एक परिमित राज्य मशीन द्वारा मिलान किया जा सकता है।

(परिमित राज्य मशीनों, पुश-डाउन मशीनों और ट्यूरिंग मशीनों को समझना मूल रूप से एक चौथे वर्ष के कॉलेज सीएस पाठ्यक्रम का पाठ्यक्रम है।)

निम्नलिखित मशीन पर विचार करें, जो स्ट्रिंग "हाय" को पहचानता है।

(Start) --Read h-->(A)--Read i-->(Succeed)
  \                  \
   \                  -- read any other value-->(Fail) 
    -- read any other value-->(Fail)

नियमित भाषा को पहचानने के लिए यह एक सरल मशीन है; कोष्ठक में प्रत्येक अभिव्यक्ति एक अवस्था है, और प्रत्येक तीर एक संक्रमण है। इस तरह से एक मशीन का निर्माण आपको किसी भी इनपुट स्ट्रिंग को नियमित भाषा के खिलाफ परीक्षण करने की अनुमति देगा - इसलिए, एक नियमित अभिव्यक्ति।

HTML में आपको यह जानने की आवश्यकता है कि आप किस स्थिति में हैं - इसमें टैग नेस्टिंग से मिलान करने के लिए आपके द्वारा पहले देखे गए इतिहास की आवश्यकता है। आप इसे पूरा कर सकते हैं यदि आप मशीन में एक स्टैक जोड़ते हैं, लेकिन फिर यह "नियमित" नहीं है। इसे पुश-डाउन मशीन कहा जाता है, और एक व्याकरण को पहचानता है।


2
"परिमित राज्य मशीनों, पुश-डाउन मशीनों और ट्यूरिंग मशीनों को समझना मूल रूप से 300-स्तरीय सीएस पाठ्यक्रम का पाठ्यक्रम है।" मैं समझता हूं कि यह बताने का प्रयास है कि विषय कितना कठिन / अग्रिम है, लेकिन मैं उस स्कूल प्रणाली से अपरिचित हूं जिसका आप उल्लेख कर रहे हैं, क्या आप गैर-विशिष्ट तरीके से स्पष्ट कर सकते हैं? धन्यवाद! :)
मैक

1
मैंने इसे अपडेट किया है। मुझे नहीं पता कि यह समझना बहुत मुश्किल है, बस एक स्टैक ओवरफ्लो पोस्ट में समझाना है।
सीन मैकमिलन

6

एक नियमित अभिव्यक्ति असतत राज्यों की परिमित (और आमतौर पर बल्कि छोटी) संख्या वाली एक मशीन है।

XML, C, या किसी अन्य भाषा को भाषा तत्वों के मनमाने तरीके से पार्स करने के लिए, आपको यह याद रखना होगा कि आप कितने गहरे हैं। यही है, आप ब्रेसिज़ / कोष्ठक / टैग को गिनने में सक्षम होना चाहिए।

आप परिमित मेमोरी के साथ गणना नहीं कर सकते। आपके पास राज्यों की तुलना में अधिक ब्रेस स्तर हो सकते हैं! आप अपनी भाषा के सबसेट को पार्स करने में सक्षम हो सकते हैं जो घोंसले के शिकार के स्तर को सीमित करता है, लेकिन यह बहुत थकाऊ होगा।


6

एक व्याकरण एक औपचारिक परिभाषा है जहाँ शब्द जा सकते हैं। उदाहरण के लिए, विशेषण संज्ञाओं को आगे बढ़ाते हैं in English grammar, लेकिन संज्ञाओं का पालन करते हैंen la gramática española । प्रसंग-मुक्त का अर्थ है कि सभी संदर्भों में सार्वभौमिक रूप से व्याकरण। प्रसंग-संवेदी साधन कुछ संदर्भों में अतिरिक्त नियम हैं।

C # में, उदाहरण के लिए, फ़ाइलों के शीर्ष पर, से usingकुछ अलग का मतलब है । एक और अधिक प्रासंगिक उदाहरण कोड के भीतर निम्नलिखित कोड है:using System;using (var sw = new StringWriter (...))

void Start ()
{
    string myCode = @"
    void Start()
    {
       Console.WriteLine (""x"");
    }
    ";
}

यह एक समझने योग्य उत्तर है
ए पर्सन

लेकिन संदर्भ-मुक्त का मतलब नियमित नहीं है। मिलान की गई परिकल्पना की भाषा संदर्भ-मुक्त है, लेकिन नियमित नहीं।
तैमूर

क्या जोड़ा जाना चाहिए कि नियमित अभिव्यक्तियाँ (जब तक कि आप इस तरह के एक्सटेंशन को पर्ल में मौजूद नहीं हैं) नियमित व्याकरण के बराबर हैं , जिसका अर्थ है कि वे मनमाने ढंग से नेस्टेड संरचनाओं जैसे मनमाने ढंग से गहराई से संतुलित कोष्ठक या एचटीएमएल तत्व खोलने और समापन टैग के रूप में वर्णित नहीं कर सकते हैं।
रीयरियरपोस्ट नोव

4

XML और HTML को पार्स करने के लिए नियमित अभिव्यक्तियों का उपयोग नहीं करने का एक और व्यावहारिक कारण है, जिसका कंप्यूटर विज्ञान सिद्धांत से कोई लेना-देना नहीं है: आपकी नियमित अभिव्यक्ति या तो छिपकर जटिल हो जाएगी, या यह गलत होगा।

उदाहरण के लिए, यह सब बहुत अच्छी तरह से मैच के लिए एक नियमित अभिव्यक्ति लिख रहा है

<price>10.65</price>

लेकिन अगर आपका कोड सही होना है, तो:

  • इसे प्रारंभ और समाप्ति टैग दोनों में तत्व नाम के बाद व्हॉट्सएप की अनुमति देनी चाहिए

  • यदि दस्तावेज़ एक नाम स्थान में है, तो उसे किसी भी नामस्थान उपसर्ग का उपयोग करने की अनुमति देनी चाहिए

  • इसे संभवतः प्रारंभ टैग (विशेष शब्दावली के शब्दार्थ के आधार पर) में दिखाई देने वाली किसी भी अज्ञात विशेषताओं की अनुमति और उपेक्षा करनी चाहिए

  • इसे दशमलव मान से पहले और बाद में व्हाट्सएप की अनुमति देने की आवश्यकता हो सकती है (फिर से, विशेष एक्सएमएल शब्दावली के विस्तृत नियमों के आधार पर)।

  • यह एक तत्व की तरह दिखने वाली किसी चीज़ से मेल नहीं खाना चाहिए, लेकिन वास्तव में एक टिप्पणी या सीडीएटीए अनुभाग में है (यह विशेष रूप से महत्वपूर्ण हो जाता है यदि आपके पार्सर को बेवकूफ बनाने की कोशिश कर रहे दुर्भावनापूर्ण डेटा की संभावना है)।

  • यदि इनपुट अमान्य है, तो उसे निदान प्रदान करने की आवश्यकता हो सकती है।

बेशक यह कुछ आपके द्वारा लागू किए जा रहे गुणवत्ता मानकों पर निर्भर करता है। हम एक विशेष तरीके से XML उत्पन्न करने वाले लोगों के साथ StackOverflow पर बहुत सारी समस्याएं देखते हैं (उदाहरण के लिए, टैग में कोई व्हाट्सएप नहीं) क्योंकि यह एक ऐसे एप्लिकेशन द्वारा पढ़ा जा रहा है जिसके लिए इसे एक विशेष तरीके से लिखा जाना चाहिए। यदि आपके कोड में किसी भी प्रकार की दीर्घायु है, तो यह महत्वपूर्ण है कि यह आने वाले XML को किसी भी तरह से लिखने में सक्षम होना चाहिए जो कि XML मानक अनुमति देता है, न कि केवल एक नमूना इनपुट दस्तावेज़ जिसे आप अपने कोड का परीक्षण कर रहे हैं।


2

विशुद्ध रूप से सैद्धांतिक अर्थ में, एक्सएमएल को पार्स करने के लिए नियमित अभिव्यक्ति के लिए असंभव है। उन्हें इस तरह से परिभाषित किया गया है, जो उन्हें किसी भी पिछले राज्य की कोई स्मृति नहीं देता है, इस प्रकार एक मनमाना टैग के सही मिलान को रोकता है, और वे घोंसले के शिकार की मनमानी गहराई तक नहीं घुस सकते हैं, क्योंकि घोंसले के शिकार को नियमित अभिव्यक्ति में बनाने की आवश्यकता होगी।

आधुनिक रेगेक्स पार्सर, हालांकि, डेवलपर के लिए उनकी उपयोगिता के लिए बनाए जाते हैं, बजाय एक सटीक परिभाषा के उनके पालन के। जैसे, हमारे पास बैक-रेफरेंस और रिकर्सन जैसी चीजें हैं जो पिछले राज्यों के ज्ञान का उपयोग करती हैं। इनका उपयोग करते हुए, एक एक्सजेक्स बनाने के लिए उल्लेखनीय रूप से सरल है जो एक्सएमएल का पता लगा सकता है, सत्यापन कर सकता है या पार्स कर सकता है।

उदाहरण के लिए विचार करें,

(?:
    <!\-\-[\S\s]*?\-\->
    |
    <([\w\-\.]+)[^>]*?
    (?:
        \/>
        |
        >
        (?:
            [^<]
            |
            (?R)
        )*
        <\/\1>
    )
)

यह अगले ठीक से बने XML टैग या टिप्पणी को खोज लेगा, और यह केवल तभी मिलेगा जब यह पूरी सामग्री ठीक से बन जाए। (नोटपैड ++ का उपयोग करके इस अभिव्यक्ति का परीक्षण किया गया है, जो बूस्ट सी ++ की रेगेक्स लाइब्रेरी का उपयोग करता है, जो एनआरई को बारीकी से विभाजित करता है।)

यहां देखिए यह कैसे काम करता है:

  1. पहला हिस्सा एक टिप्पणी से मेल खाता है। इसके लिए पहले आना आवश्यक है ताकि यह किसी भी टिप्पणी-आउट कोड से निपट ले जो अन्यथा हैंग हो सकता है।
  2. यदि यह मेल नहीं खाता है, तो यह एक टैग की शुरुआत के लिए दिखेगा। ध्यान दें कि यह नाम पर कब्जा करने के लिए कोष्ठक का उपयोग करता है।
  3. यह टैग या तो समाप्त हो जाएगा />, इस प्रकार टैग को पूरा करेगा, या यह एक के साथ समाप्त होगा >, जिस स्थिति में यह टैग की सामग्री की जांच करके जारी रहेगा।
  4. यह तब तक पार्सिंग जारी रखेगा जब तक कि यह एक <बिंदु तक नहीं पहुंच जाता है , जिस समय यह अभिव्यक्ति की शुरुआत में वापस आ जाएगा, यह एक टिप्पणी या एक नए टैग से निपटने की अनुमति देगा।
  5. यह लूप के माध्यम से तब तक जारी रहेगा जब तक <कि यह पाठ के अंत में नहीं आता है या जब तक यह पार्स नहीं कर सकता है। निश्चित रूप से, यह प्रक्रिया खत्म होने का कारण बन सकता है। अन्यथा, <संभवतः इस पुनरावृत्ति के लिए समापन टैग की शुरुआत है। समापन टैग के अंदर बैक-रेफरेंस का उपयोग करके <\/\1>, यह वर्तमान पुनरावृत्ति (गहराई) के लिए शुरुआती टैग से मेल खाएगा। केवल एक कैप्चरिंग ग्रुप है, इसलिए यह मैच एक साधारण मामला है। यह इसे उपयोग किए गए टैगों के नामों से स्वतंत्र बनाता है, हालांकि आप कैप्चरिंग समूह को केवल विशिष्ट टैग को कैप्चर करने के लिए संशोधित कर सकते हैं, यदि आपको आवश्यकता है।
  6. इस बिंदु पर यह या तो वर्तमान पुनरावृत्ति से बाहर हो जाएगा, अगले स्तर तक या एक मैच के साथ समाप्त होगा।

यह उदाहरण व्हाट्सएप से निपटने में समस्या का समाधान करता है या चरित्र समूहों के उपयोग के माध्यम से प्रासंगिक सामग्री की पहचान करता है जो केवल नकारात्मक <या >टिप्पणी के मामले में उपयोग करते हैं [\S\s], जो कुछ भी मैच करेगा, जिसमें गाड़ी के रिटर्न और नई लाइनें भी शामिल हैं, यहां तक ​​कि एकल-पंक्ति में भी मोड, जारी रखने तक यह एक तक पहुँचता है -->। इसलिए, जब तक यह कुछ सार्थक नहीं हो जाता है, तब तक यह सब कुछ वैध मानता है।

अधिकांश उद्देश्यों के लिए, इस तरह का एक रेक्सक्स विशेष रूप से उपयोगी नहीं है। यह पुष्टि करेगा कि XML ठीक से बना है, लेकिन यह सब वास्तव में होगा, और यह गुणों का हिसाब नहीं देता है (हालांकि यह एक आसान विकल्प होगा)। यह केवल यह सरल है क्योंकि यह वास्तविक दुनिया के मुद्दों को छोड़ देता है, साथ ही साथ टैग नामों की परिभाषा भी। वास्तविक उपयोग के लिए इसे फिट करने से यह बहुत अधिक जानवर बन जाएगा। सामान्य तौर पर, एक सच्चा XML पार्सर कहीं बेहतर होगा। यह एक शिक्षण के लिए शायद सबसे उपयुक्त है कि कैसे काम करता है।

लंबी कहानी छोटी: वास्तविक काम के लिए एक XML पार्सर का उपयोग करें, और यदि आप regexes के साथ खेलना चाहते हैं तो इसका उपयोग करें।


3
यह कथन कि यह रेगेक्स केवल तभी मेल करेगा जब इनपुट अच्छी तरह से बना हो, गलत है। यह जांच नहीं करता है कि नाम वैध XML नाम हैं, यह विशेषताओं की जांच नहीं करता है, यह इकाई और चरित्र संदर्भों की जांच नहीं करता है, यह सीडीएटीए या प्रसंस्करण निर्देश नहीं संभालता है। जब आप कहते हैं कि इसका परीक्षण किया गया है, तो मुझे बहुत संदेह है कि यह XML अनुरूपता परीक्षण सूट के समान किसी भी चीज पर परीक्षण किया गया है। यह समस्या है कि मैंने कभी देखा है regexes के साथ XML को संसाधित करने के सभी प्रयासों के साथ: वे इनपुट की एक छोटी संख्या के साथ काम करते हैं, लेकिन किसी भी XML के साथ नहीं जो कानूनी रूप से आपके आवेदन को पारित किया जा सकता है।
माइकल काय

2
इसके अलावा, अच्छी तरह से गठित इनपुट हैं जो रेगेक्स से मेल नहीं खाते हैं। उदाहरण के लिए, यह अंतिम टैग में नाम के बाद व्हॉट्सएप की अनुमति नहीं देता है। इनमें से अधिकांश ग्लिच आसानी से तय हो जाते हैं, लेकिन एक बार जब आप सभी ग्लिच को ठीक कर लेते हैं तो आप पूरी तरह से बेकार हो जाते हैं। और निश्चित रूप से असली गोचा यह है कि आप केवल एक पार्सर नहीं चाहते कि वह आपको हां / ना में जवाब दे, आप चाहते हैं कि यह एक ऐसे एप्लिकेशन को जानकारी दे जो इसके साथ कुछ उपयोगी हो।
माइकल काय

0

रेगेक्स के साथ XML / HTML को पार्स न करें, एक उचित XML / HTML पार्सर और एक शक्तिशाली का उपयोग करें क्वेरी।

सिद्धांत:

संकलन सिद्धांत के अनुसार, XML / HTML को परिमित राज्य मशीन के आधार पर regex का उपयोग करके पार्स नहीं किया जा सकता है । XML / HTML के पदानुक्रमित निर्माण के कारण आपको एक पुशडाउन ऑटोमेटन का उपयोग करने और हेरफेर करने की आवश्यकता है LALR तरह उपकरण का उपयोग व्याकरण YACC

realLife © ® ™ रोज़ टूल इन a :

आप निम्न में से किसी एक का उपयोग कर सकते हैं:

xmllint को अक्सर डिफ़ॉल्ट रूप से स्थापित किया जाता है libxml2, xpath1 ( मेरे रैपर की जांच करें जिसमें न्यूलाइज़ सीमांकित आउटपुट हो

xmlstarlet एडिट, सेलेक्ट, ट्रांसफॉर्म कर सकता है ... डिफ़ॉल्ट रूप से स्थापित नहीं, xpath1

xpath पर्ल के मॉड्यूल XML के माध्यम से स्थापित किया गया :: XPath, xpath1

xidel xpath3

सेक्सन-फाहा मेरी खुद की परियोजना, @Michael Kay की Saxon-HE जावा पुस्तकालय, xpath3 पर आवरण

या आप उच्च स्तरीय भाषाओं और उचित लिबास का उपयोग कर सकते हैं, मुझे लगता है:

की lxml( from lxml import etree)

's XML::LibXML, XML::XPath, XML::Twig::XPath,HTML::TreeBuilder::XPath

, इस उदाहरण की जाँच

DOMXpath, इस उदाहरण की जाँच


जांचें: HTML टैग के साथ नियमित अभिव्यक्तियों का उपयोग करना

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.