Dokumenty XML są standardem przechowywania i przekazywania
danych. Xpath natomiast jest jedną z podstawowych metod przeszukiwania XMLi. Jak więc w Pythonie przeszukiwać xmle?
Python posiada w bibliotece standardowej parser XML - moduł
xml. Jednak moduł ten ma ograniczone wsparcie dla XPath (zobacz
xpath
support na docs.python.org). Bogatsze wsparcie dla XPath zapewnia
biblioteka
lxml, oparta na libxml2 i libxslt - dobrze rozwiniętych i
dostępnych na wiele platform bibliotek. lxml można łatwo zainstalować
przy pomocy pip-a, jest wśród standardowych
pakietów anacondy, a ze
względu na zależności często jest zainstalowany także na linuxowych
systemach (zależy od niego np. Inkscape i Cinnamon).
Poniższy program, kompatybilny z Python 3, przedstawia przykłady użycia lxml do parsowania XML z wykorzystaniem XPath.
'''przykladowy program parsujacy XMLe'''
from lxml import etree
# przykladowy xml wczytany bezposrednio z lancucha bajtow.
xml = etree.fromstring(b'''<?xml version="1.0" encoding="UTF-8"?>
<ksiazki>
<ksiazka>
<tytul lang="pl">Pan Tadeusz</tytul>
<autor>A. Mickiewicz</autor>
<rok>2012</rok>
<cena>31.99</cena>
</ksiazka>
<ksiazka>
<tytul lang="pl">Antygona</tytul>
<autor>Sofokles</autor>
<rok>2006</rok>
<cena>5.99</cena>
</ksiazka>
<f:ksiazka xmlns:f="https://wrobelmaciek.blogspot.com/ksiazki">
<f:tytul lang="pl">Emocjonalne wampiry w pracy</f:tytul>
<f:autor>A. B. Bernstein</f:autor>
<f:rok>2014</f:rok>
<f:cena>37.90</f:cena>
</f:ksiazka>
</ksiazki>
''')
#metoda xpath zwraca liste elementow spelniajacych kryteria
#elementy sa objektami, mozna odczytac ich tekst, wziac przodka,
#atrybuty itd.
print('autorzy ksiazek i jezyk tytulu')
for el in xml.xpath('.//autor'):
print('{0}:{1}'.format(el.text,
el.getparent().find('tytul').get('lang'), ))
#lxml obsluguje tez bardziej zlozone zapytania
print('tytuly ksiazek zaczynajace sie na A:')
print('\n'.join([x.text for x in
xml.xpath('.//*[name()="tytul" and starts-with(text(),"A")]')]))
#lxml obsluguje tez przestrzenie nazw (namespaces)
print('''autorzy o nazwiskach zaczynajacych sie na A,
niezależnie od przestrzeni nazw:''')
print('\n'.join(['%s %s'%(x.tag,x.text,) for x in
xml.xpath('.//*[local-name()="autor" and starts-with(text(),"A")]')]))
print('''ksiazki o autorach zaczynajacych sie na A,
z przestrzeni nazw {https://wrobelmaciek.blogspot.com/ksiazki}:''')
print('\n'.join(['%s %s'%(x.tag,x.text,) for x in
xml.xpath('.//g:autor[starts-with(text(),"A")]',
namespaces={'g':'https://wrobelmaciek.blogspot.com/ksiazki'})]))
#jesli nie potrzebujemy zlozonych zapytan, mozemy uzyc tez findall
#kompatybilnego z xml.ElementTree z biblioteki standardowej pythona
print('autorzy ksiazek i jezyk tytulu - findall')
for el in xml.findall('.//autor'):
print('{0}:{1}'.format(el.text,
el.getparent().find('tytul').get('lang'), ))
#findall obsluguje tylko najprostsze zapytania XPath
try:
print('to nie zadziala')
for el in xml.findall('.//*[name()="autor"]'):
print('{0}:{1}'.format(el.text,
el.getparent().find('tytul').get('lang'),
))
except SyntaxError:
print('zbyt skomplikowany predykat')