2010-11-18 14 views
19

मैं ओपनऑफिस ओडीएस स्प्रेडशीट में सामग्री का विश्लेषण करने की कोशिश कर रहा हूं। ओडीएस प्रारूप अनिवार्य रूप से केवल एक दस्तावेज के साथ एक ज़िपफाइल है। स्प्रेडशीट की सामग्री 'content.xml' में संग्रहीत है।मैं xx नेमस्पेस का उपयोग lxml में ढूंढ/ढूंढने के साथ कैसे करूं?

table = root.find('.//{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table') 

हम भी पंक्तियों के लिए सीधे जा सकते हैं:

rows = root.findall('.//{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table-row') 

अलग-अलग तत्वों नामस्थान के बारे में पता:

import zipfile 
from lxml import etree 

zf = zipfile.ZipFile('spreadsheet.ods') 
root = etree.parse(zf.open('content.xml')) 

स्प्रैडशीट की सामग्री में एक सेल में है

>>> table.nsmap['table'] 
'urn:oasis:names:tc:opendocument:xmlns:table:1.0' 

कैसे कर मैं नेमस्पेस का उपयोग सीधे ढूंढने/ढूंढने में करता हूं?

स्पष्ट समाधान काम नहीं करता।

मेज से पंक्तियां प्राप्त करने की कोशिश कर रहा:

>>> root.findall('.//table:table') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "lxml.etree.pyx", line 1792, in lxml.etree._ElementTree.findall (src/lxml/lxml.etree.c:41770) 
    File "lxml.etree.pyx", line 1297, in lxml.etree._Element.findall (src/lxml/lxml.etree.c:37027) 
    File "/usr/lib/python2.6/dist-packages/lxml/_elementpath.py", line 225, in findall 
    return list(iterfind(elem, path)) 
    File "/usr/lib/python2.6/dist-packages/lxml/_elementpath.py", line 200, in iterfind 
    selector = _build_path_iterator(path) 
    File "/usr/lib/python2.6/dist-packages/lxml/_elementpath.py", line 184, in _build_path_iterator 
    selector.append(ops[token[0]](_next, token)) 
KeyError: ':' 
+0

आप स्प्रेडशीट संसाधित करने OpenOffice के लिए अजगर एपीआई का उपयोग करने की कोशिश की है? – jfs

+0

नमस्ते मैं नामस्थान के साथ तत्वों और विशेषताओं तक पहुंचने के लिए etree.QName का उपयोग कर रहा हूं। नामस्थानों के शब्दकोश की सहायता से यह एक साफ तरीका है, और यह ढूंढने और खोजने के तरीके के साथ भी काम करता है। अधिक जानकारी के लिए कृपया देखें: http://lxml.de/tutorial.html#namespaces –

उत्तर

16

तो root.nsmap आप कर सकते थे तो table नामस्थान उपसर्ग शामिल हैं:

root.xpath('.//table:table', namespaces=root.nsmap) 

findall(path)namespace:name के बजाय {namespace}name वाक्य रचना स्वीकार करता है। इसलिए path यह findall() को पार करने से पहले {namespace}name फार्म के लिए नाम स्थान शब्दकोश का उपयोग कर preprocessed किया जाना चाहिए।

+0

दिलचस्प है, लेकिन कम-स्तर की समस्या प्रतीत होती है: table.xpath ('.// ​​table: table-row', nsmap = table.nsmap) *** XPathResultError: अज्ञात वापसी प्रकार: dict – saffsd

+0

@saffsd: नोट: * नेमस्पेस = * नहीं * nsmap = *। आज़माएं: 'root.xpath (' .// टेबल: टेबल-पंक्ति ', नेमस्पेस = {' टेबल ':' urn: oasis: names: tc: opendocument: xmlns: table: 1.0 '}) ' – jfs

6

यहाँ एक तरह से XML दस्तावेज़ में सभी नामस्थान प्राप्त करने के लिए है (और मान कोई उपसर्ग संघर्ष है)।

मैं इस का उपयोग करते हैं एक्सएमएल दस्तावेजों जहाँ मैं पहले से जानते हो क्या नाम स्थान यूआरएल हैं, और केवल उपसर्ग को पार्स।

 doc = etree.XML(XML_string) 

     # Getting all the name spaces. 
     nsmap = {} 
     for ns in doc.xpath('//namespace::*'): 
      if ns[0]: # Removes the None namespace, neither needed nor supported. 
       nsmap[ns[0]] = ns[1] 
     doc.xpath('//prefix:element', namespaces=nsmap) 
5

हो सकता है कि सूचना के लिए पहली बात यह है कि नामस्थान तत्व स्तर, नहीं दस्तावेज़ स्तर पर निर्धारित कर रहे हैं।

अक्सर हालांकि, सभी नामस्थान दस्तावेज़ के मूल तत्व (office:document-content यहाँ) है, जो हमें यह सब भीतरी xmlns स्कोप इकट्ठा करने के लिए पार्स करने बचाता घोषित किये गए हैं।

फिर एक तत्व nsmap में शामिल हैं:

  • एक डिफ़ॉल्ट नाम स्थान, None उपसर्ग (हमेशा)
  • सभी पूर्वजों नामस्थान, जब तक ओवरराइड साथ।

हैं, के रूप में ChrisR mentionned, डिफ़ॉल्ट नाम स्थान समर्थित नहीं है, आप एक अधिक कॉम्पैक्ट अभिव्यक्ति में इसे बाहर फिल्टर करने के लिए एक dict comprehension उपयोग कर सकते हैं।

आपके पास xpath और ElementPath के लिए थोड़ा अलग वाक्यविन्यास है। (के साथ परीक्षण किया: lxml=3.4.2):


तो यहाँ कोड आप अपने सभी पहले तालिका पंक्तियों प्राप्त करने के लिए इस्तेमाल कर सकते हैं है

import zipfile 
from lxml import etree 

# Open and parse the document 
zf = zipfile.ZipFile('spreadsheet.ods') 
tree = etree.parse(zf.open('content.xml')) 

# Get the root element 
root = tree.getroot() 

# get its namespace map, excluding default namespace 
nsmap = {k:v for k,v in root.nsmap.iteritems() if k} 

# use defined prefixes to access elements 
table = tree.find('.//table:table', nsmap) 
rows = table.findall('table:table-row', nsmap) 

# or, if xpath is needed: 
table = tree.xpath('//table:table', namespaces=nsmap)[0] 
rows = table.xpath('table:table-row', namespaces=nsmap) 
+0

यदि आपको आवश्यकता है nsmap जिसमें डिफ़ॉल्ट नेमस्पेस शामिल है, उपयोग करें (पायथन 3): 'nsmap = {k if k कोई और नहीं है 'डिफ़ॉल्ट': v के लिए v, v में root.nsmap.items()}' – skelliam

+0

पायथन 3 के लिए iteritems का नाम बदलें () केवल वस्तुओं() के ऊपर। – skelliam

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