2008-11-17 8 views
21

मैं निम्नलिखित परीक्षण दस्तावेज़ के खिलाफ परीक्षण कर रहा हूँ:,lxml (पायथन में) के साथ एक एक्सएचटीएमएल दस्तावेज़ को संसाधित करते समय xpath क्यों काम नहीं करता है?

>>> root = lxml.html.fromstring(doc) 
>>> root.xpath("//img") 
[<Element img at 1879e30>] 

लेकिन अगर मैं:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <title>hi there</title> 
    </head> 
    <body> 
     <img class="foo" src="bar.png"/> 
    </body> 
</html> 

अगर मैं lxml.html का उपयोग कर दस्तावेज़ को पार्स, मैं एक xpath ठीक से आईएमजी प्राप्त कर सकते हैं

>>> tree = etree.parse(StringIO(doc)) 
>>> tree.getroot().xpath("//img") 
[] 

मैं तत्व सीधे नेविगेट कर सकते हैं: XML के रूप में दस्तावेज़ को पार्स और आईएमजी टैग प्राप्त करने की कोशिश, मैं एक खाली परिणाम प्राप्त

0,123,
>>> tree.getroot().getchildren()[1].getchildren()[0] 
<Element {http://www.w3.org/1999/xhtml}img at f56810> 

लेकिन निश्चित रूप से यह मुझे मनमानी दस्तावेजों को संसाधित करने में मदद नहीं करता है। मैं भी etree क्वेरी करने के लिए एक xpath एक्सप्रेशन कि सीधे इस तत्व है, जो, तकनीकी रूप से मैं क्या कर सकते हैं की पहचान करेगा प्राप्त करने में सक्षम होने की अपेक्षा करेंगे:

>>> tree.getpath(tree.getroot().getchildren()[1].getchildren()[0]) 
'/*/*[2]/*' 
>>> tree.getroot().xpath('/*/*[2]/*') 
[<Element {http://www.w3.org/1999/xhtml}img at fa1750>] 

लेकिन उस xpath, फिर से मनमाने ढंग से दस्तावेज पार्स करने के लिए उपयोगी नहीं है, स्पष्ट रूप से ।

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

तो, मुझे क्या याद आ रही है?

उत्तर

27

समस्या नामस्थान है। एक्सएमएल के रूप में पार्स किए जाने पर, आईएमजी टैग http://www.w3.org/1999/xhtml नेमस्पेस में है क्योंकि यह तत्व के लिए डिफ़ॉल्ट नामस्थान है। आप आईएमजी टैग के लिए नामस्थान में पूछ रहे हैं।

इस प्रयास करें:

>>> tree.getroot().xpath(
...  "//xhtml:img", 
...  namespaces={'xhtml':'http://www.w3.org/1999/xhtml'} 
... ) 
[<Element {http://www.w3.org/1999/xhtml}img at 11a29e0>] 
+0

की जाँच से हवाला देते हुए http://codespeak.net/lxml/xpathxslt.html << वैकल्पिक रूप से, आप एक नामस्थान कीवर्ड तर्क है, जो एक शब्दकोश मानचित्रण होना चाहिए प्रदान कर सकते हैं नामस्थान उपसर्गों को नामस्थान यूआरआई के लिए XPath अभिव्यक्ति में उपयोग किया जाता है >> –

+0

यदि आप मूल तत्व के डिफ़ॉल्ट नामस्थान में कॉम्पैक्ट xpath अभिव्यक्तियों के साथ खोजना चाहते हैं, तो आप एक चाल का उपयोग कर सकते हैं जो xhtml या अन्य स्कीमा के लिए काम करता है, जैसे कुछ: 'nsmap = {'एच': tree.getroot()। nsmap [कोई नहीं]}; elem.xpath ('// h: img', namespaces = nsmap' - जो क्वेरी को कॉम्पैक्टली लिखना आसान बनाता है। – mkj

7

XPath considers all unprefixed names to be in "no namespace"

विशेष रूप से कल्पना का कहना है:

"नोड परीक्षण में एक QName अभिव्यक्ति संदर्भ से नाम स्थान घोषणाओं का उपयोग कर एक विस्तारित नाम में विस्तार किया है, तो यह एक ही तरह से विस्तार में तत्व प्रकार के नाम के लिए किया जाता है। प्रारंभ और अंत टैग जो कि xmlns के साथ घोषित डिफ़ॉल्ट नामस्थान का उपयोग नहीं किया जाता है: यदि QName में उपसर्ग नहीं है, तो नामस्थान यूआरआई शून्य है (यह वही तरीका है विशेषता गुणों का विस्तार किया गया है)। "

देखें समस्या और उसके समाधान के उन दो विस्तृत स्पष्टीकरण: here और here। समाधान एक उपसर्ग (एपीआई के साथ उपयोग किया जा रहा है) को जोड़ने और XPath अभिव्यक्ति में किसी भी अपरिवर्तित नाम को उपसर्ग करने के लिए इसका उपयोग करने के लिए है।

आशा है कि इससे मदद मिलेगी।

चीयर्स,

Dimitre Novatchev

2

आप केवल एक ही नाम स्थान से टैग का उपयोग करने, के रूप में मैं इसे उपरोक्त मामले को देखने के लिए जा रहे हैं, तो आप lxml.objectify का उपयोग कर बंद काफी बेहतर हैं।

आपके मामले में ऐसा

from lxml import objectify 
root = objectify.parse(url) #also available: fromstring 

आप के रूप

root.html 
body = root.html.body 
for img in body.img: #Assuming all images are within the body tag 

यह html में बहुत मदद की नहीं हो सकती है, यह अच्छी तरह से संरचित में बहुत उपयोगी हो सकता नोड्स का उपयोग कर सकते हो जाएगा एक्सएमएल।

अधिक जानकारी के लिए, http://lxml.de/objectify.html

संबंधित मुद्दे