2010-09-24 24 views
7

Python elementTree sembra inutilizzabile con namespace. Quali sono le mie alternative? BeautifulSoup è piuttosto spazzatura con lo spazio dei nomi. Non voglio spogliarli.Buon parser XML Python per lavorare con documenti pesanti namespace

Esempi di come una particolare libreria Python ottiene gli elementi dello spazio dei nomi e le loro raccolte sono tutti +1.

Modifica: Potrebbe fornire il codice per gestire questo caso di utilizzo del mondo reale utilizzando la libreria preferita?

Come si va su come ottenere le stringhe 'linea di rottura', '2.6' e una lista [ 'PITONE', 'XML', 'XML-NAMESPACES']

<?xml version="1.0" encoding="UTF-8"?> 
<zs:searchRetrieveResponse 
    xmlns="http://unilexicon.com/vocabularies/" 
    xmlns:zs="http://www.loc.gov/zing/srw/" 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:lom="http://ltsc.ieee.org/xsd/LOM"> 
    <zs:records> 
     <zs:record> 
      <zs:recordData> 
       <srw_dc:dc xmlns:srw_dc="info:srw/schema/1/dc-schema"> 
        <name>Line Break</name> 
        <dc:title>Processing XML namespaces using Python</dc:title> 
        <dc:description>How to get contents string from an element, 
         how to get a collection in a list...</dc:description> 
        <lom:metaMetadata> 
         <lom:identifier> 
          <lom:catalog>Python</lom:catalog> 
          <lom:entry>2.6</lom:entry> 
         </lom:identifier> 
        </lom:metaMetadata> 
        <lom:classification> 
         <lom:taxonPath> 
          <lom:taxon> 
           <lom:id>PYTHON</lom:id> 
          </lom:taxon> 
         </lom:taxonPath> 
        </lom:classification> 
        <lom:classification> 
         <lom:taxonPath> 
          <lom:taxon> 
           <lom:id>XML</lom:id> 
          </lom:taxon> 
         </lom:taxonPath> 
        </lom:classification> 
        <lom:classification> 
         <lom:taxonPath> 
          <lom:taxon> 
           <lom:id>XML-NAMESPACES</lom:id> 
          </lom:taxon> 
         </lom:taxonPath> 
        </lom:classification> 
       </srw_dc:dc> 
      </zs:recordData> 
     </zs:record> 
     <!-- ... more records ... --> 
    </zs:records> 
</zs:searchRetrieveResponse> 
+1

amo la natura meta della vostra MWE. –

+0

Utilizzando parole chiave pertinenti nel codice di esempio significa che più utenti possono trovare la domanda e le risposte. –

risposta

12

lxml è sensibile allo spazio dei nomi.

>>> from lxml import etree 
>>> et = etree.XML("""<root xmlns="foo" xmlns:stuff="bar"><bar><stuff:baz /></bar></root>""") 
>>> etree.tostring(et, encoding=str) # encoding=str only needed in Python 3, to avoid getting bytes 
'<root xmlns="foo" xmlns:stuff="bar"><bar><stuff:baz/></bar></root>' 
>>> et.xpath("f:bar", namespaces={"b":"bar", "f": "foo"}) 
[<Element {foo}bar at ...>] 

Edit: Sul tuo esempio:

from lxml import etree 

# remove the b prefix in Python 2 
# needed in python 3 because 
# "Unicode strings with encoding declaration are not supported." 
et = etree.XML(b"""...""") 

ns = { 
    'lom': 'http://ltsc.ieee.org/xsd/LOM', 
    'zs': 'http://www.loc.gov/zing/srw/', 
    'dc': 'http://purl.org/dc/elements/1.1/', 
    'voc': 'http://www.schooletc.co.uk/vocabularies/', 
    'srw_dc': 'info:srw/schema/1/dc-schema' 
} 

# according to docs, .xpath returns always lists when querying for elements 
# .find returns one element, but only supports a subset of XPath 
record = et.xpath("zs:records/zs:record", namespaces=ns)[0] 
# in this example, we know there's only one record 
# but else, you should apply the following to all elements the above returns 

name = record.xpath("//voc:name", namespaces=ns)[0].text 
print("name:", name) 

lom_entry = record.xpath("zs:recordData/srw_dc:dc/" 
         "lom:metaMetadata/lom:identifier/" 
         "lom:entry", 
         namespaces=ns)[0].text 

print('lom_entry:', lom_entry) 

lom_ids = [id.text for id in 
      record.xpath("zs:recordData/srw_dc:dc/" 
         "lom:classification/lom:taxonPath/" 
         "lom:taxon/lom:id", 
         namespaces=ns)] 

print("lom_ids:", lom_ids) 

uscita:

name: Frank Malina 
lom_entry: 2.6 
lom_ids: ['PYTHON', 'XML', 'XML-NAMESPACES'] 
+2

+1 lxml è l'unico strumento/pacchetto python necessario per le attività relative a xml/xslt/xpath – snapshoe

+0

Modifica: come si codificherà l'esempio fornito? La mancanza di ricette sul web per questo tipo di lavoro su XML è spaventosa. Al momento, ho proceduto spogliando gli spazi dei nomi e attraversando con BeautifulSoup. Questo è non ottimale su un numero di livelli. –

+0

@Frank Malina: XPath non è specifico per XML, ci sono alcune risorse utilizzabili su XPath attraverso il web. Ma farò una pugnalata a questo ... – delnan

0

libxml (http://xmlsoft.org/) migliore, più veloce per i lib xml parsing. Esistono implementazioni per python.

+4

lxml da codespeak avvolge e utilizza libxml – snapshoe