xml xml - Wie verwende ich Xpath in Python?




dom example (10)

Klingt wie eine Lxml Werbung hier drin. ;) ElementTree ist in der Std-Bibliothek enthalten. Unter 2.6 und darunter ist sein XPath ziemlich schwach, aber in 2.7 sehr verbessert :

import xml.etree.ElementTree as ET
root = ET.parse(filename)
result = ''

for elem in root.findall('.//child/grandchild'):
    # How to make decisions based on attributes even in 2.6:
    if elem.attrib.get('name') == 'foo':
        result = elem.text
        break

Was ist die Bibliothek? Gibt es eine vollständige Implementierung? Wie wird die Bibliothek verwendet? Wo ist seine Website?


Sie können verwenden:

PyXML :

from xml.dom.ext.reader import Sax2
from xml import xpath
doc = Sax2.FromXmlFile('foo.xml').documentElement
for url in xpath.Evaluate('//@Url', doc):
  print url.value

libxml2 :

import libxml2
doc = libxml2.parseFile('foo.xml')
for url in doc.xpathEval('//@Url'):
  print url.content

libxml2 hat eine Reihe von Vorteilen:

  1. Übereinstimmung mit der spec
  2. Aktive Entwicklung und eine Gemeinschaftsbeteiligung
  3. Geschwindigkeit. Dies ist wirklich ein Python-Wrapper um eine C-Implementierung.
  4. Allgegenwart. Die Bibliothek libxml2 ist allgegenwärtig und daher gut getestet.

Nachteile sind:

  1. Übereinstimmung mit der spec . Es ist streng. Dinge wie Standard-Namespace-Behandlung sind einfacher in anderen Bibliotheken.
  2. Verwendung von nativem Code Je nachdem, wie Ihre Anwendung verteilt / bereitgestellt wird, kann dies sehr schmerzhaft sein. RPMs sind verfügbar, die einige dieser Schmerzen lindern.
  3. Manuelle Ressourcenverwaltung Beachten Sie im folgenden Beispiel die Aufrufe von freeDoc () und xpathFreeContext (). Das ist nicht sehr pythonisch.

Wenn Sie eine einfache ElementTree , bleiben Sie bei ElementTree (das in Python 2.5 enthalten ist). Wenn Sie die volle Spezifikationskonformität oder rohe Geschwindigkeit benötigen und die Verteilung von systemeigenem Code bewältigen können, gehen Sie mit libxml2.

Beispiel für die Verwendung von libxml2 XPath

import libxml2

doc = libxml2.parseFile("tst.xml")
ctxt = doc.xpathNewContext()
res = ctxt.xpathEval("//*")
if len(res) != 2:
    print "xpath query: wrong node set size"
    sys.exit(1)
if res[0].name != "doc" or res[1].name != "foo":
    print "xpath query: wrong node set value"
    sys.exit(1)
doc.freeDoc()
ctxt.xpathFreeContext()

Beispiel für die Verwendung von ElementTree XPath

from elementtree.ElementTree import ElementTree
mydoc = ElementTree(file='tst.xml')
for e in mydoc.findall('/foo/bar'):
    print e.get('title').text

Sie können den einfachen soupparser von lxml

Beispiel:

from lxml.html.soupparser import fromstring

tree = fromstring("<a>Find me!</a>")
print tree.xpath("//a/text()")

Die neueste Version von ElementTree unterstützt XPath ziemlich gut. Da ich kein XPath-Experte bin, kann ich nicht mit Sicherheit sagen, ob die Implementierung voll ist, aber es hat die meisten meiner Bedürfnisse befriedigt, wenn ich in Python arbeite. Ich benutze auch lxml und PyXML und finde es sehr nett, weil es ein Standardmodul ist.

HINWEIS: Ich habe seitdem lxml gefunden und für mich ist es definitiv die beste XML-Bibliothek für Python. Es macht auch XPath schön (obwohl wieder vielleicht keine vollständige Implementierung).


PyXML funktioniert gut.

Sie haben nicht gesagt, welche Plattform Sie verwenden, aber wenn Sie auf Ubuntu sind, können Sie es mit sudo apt-get install python-xml . Ich bin mir sicher, dass es auch andere Linux-Distributionen haben.

Wenn Sie auf einem Mac arbeiten, ist Xpath bereits installiert, aber nicht sofort zugänglich. Sie können PY_USE_XMLPLUS in Ihrer Umgebung PY_USE_XMLPLUS oder die Python-Methode ausführen, bevor Sie xml.xpath importieren:

if sys.platform.startswith('darwin'):
    os.environ['PY_USE_XMLPLUS'] = '1'

Im schlimmsten Fall müssen Sie es vielleicht selbst bauen. Dieses Paket wird nicht mehr gewartet, aber es funktioniert immer noch gut und funktioniert mit modernen 2.x Pythons. Grundlegende Dokumente sind here .


Wenn Sie die Leistungsfähigkeit von XPATH in Kombination mit der Möglichkeit haben möchten, CSS auch zu jedem Zeitpunkt zu verwenden, können Sie parsel :

>>> from parsel import Selector
>>> sel = Selector(text=u"""<html>
        <body>
            <h1>Hello, Parsel!</h1>
            <ul>
                <li><a href="http://example.com">Link 1</a></li>
                <li><a href="http://scrapy.org">Link 2</a></li>
            </ul
        </body>
        </html>""")
>>>
>>> sel.css('h1::text').extract_first()
'Hello, Parsel!'
>>> sel.xpath('//h1/text()').extract_first()
'Hello, Parsel!'

Verwenden Sie LXML. LXML verwendet die volle Leistung von libxml2 und libxslt, umschließt sie jedoch in mehr "Pythonic" -Bindungen als die Python-Bindungen, die in diesen Bibliotheken enthalten sind. Als solches erhält es die vollständige XPath 1.0-Implementierung. Native ElementTree unterstützt eine begrenzte Teilmenge von XPath, obwohl es für Ihre Bedürfnisse gut genug sein könnte.


Eine andere Bibliothek ist 4Suite: http://sourceforge.net/projects/foursuite/

Ich weiß nicht, wie spezifikationskonform es ist. Aber es hat sehr gut für meinen Gebrauch funktioniert. Es sieht verlassen aus.


Im Gegensatz zu isfile() gibt exists() für Verzeichnisse True .
Abhängig davon, ob Sie nur einfache Dateien oder auch Verzeichnisse wünschen, verwenden Sie isfile() oder exists() . Hier ist eine einfache REPL-Ausgabe.

>>> print os.path.isfile("/etc/password.txt")
True
>>> print os.path.isfile("/etc")
False
>>> print os.path.isfile("/does/not/exist")
False
>>> print os.path.exists("/etc/password.txt")
True
>>> print os.path.exists("/etc")
True
>>> print os.path.exists("/does/not/exist")
False




python xml dom xpath nodes