Jak analizować pliki XML za pomocą Pythona?

Jak analizować pliki XML za pomocą Pythona?

Od zamawiania artykułów spożywczych przez Instamart i zakupy garderoby w Myntrze po rezerwację wakacji na MakemyTrip, strony internetowe stały się nieodzowne w tej dekadzie! Czy zastanawiałeś się kiedyś, w jaki sposób te witryny wyświetlają klientom informacje w łatwy do interpretacji sposób, a także przetwarzają i wchodzą w interakcję z danymi w zapleczu?

Istnieją pewne formaty plików, które wypełniają tę lukę, dając się interpretować zarówno dla języka maszynowego, jak i dla ludzi. Jednym z takich powszechnie używanych formatów jest XML, który jest skrótem od Extensible Markup Language.

Czym są pliki XML i jak ich używamy?

Pliki XML służą do przechowywania i przesyłania danych między klientami a serwerami. Pozwala nam definiować dane w ustrukturyzowanym formacie za pomocą tagów, atrybutów i wartości. Jedną z głównych zalet XML jest jego elastyczność. Może być używany do reprezentowania danych w wielu formatach i łatwo dostosowywany do nowych zastosowań. To sprawia, że ​​jest popularnym wyborem dla aplikacji, takich jak usługi sieciowe, wymiana danych i pliki konfiguracyjne. W tym artykule przeprowadzę cię przez różne metody w Pythonie, aby przeanalizować plik XML z praktycznym przykładem.


Szukasz automatycznego parsowania XML? Wypróbuj zautomatyzowane przepływy pracy Nanonets. Rozpocznij bezpłatną wersję próbną już teraz.


Zrozumienie struktury plików XML

Zanim zagłębimy się w szczegóły analizowania plików XML, najpierw zapoznajmy się z różnymi częściami dokumentu XML. W XML, np element jest podstawowym budulcem dokumentu, który reprezentuje ustrukturyzowaną informację. Zawartość elementu musi być zawsze umieszczona pomiędzy tagiem otwierającym i zamykającym, jak pokazano poniżej.

Harry Potter i Kamień Filozoficzny

Użyję przykładowego pliku „travel_pckgs.xml”, który zawiera szczegółowe informacje o różnych pakietach wycieczek oferowanych przez firmę. Będę nadal używać tego samego pliku na całym blogu dla jasności.

<?xml version="1.0"?>
<travelPackages>
<package id='Paris vacation'>
<description>Experience the magnificent beauty of Paris and the french culture.</description>
<destination>Paris, France</destination>
<price>3000</price>
<duration>7</duration>
<payment>
<EMIoption>yes</EMIoption>
<refund>yes</refund>
</payment>
</package>
<package id='Hawaii Adventure'>
<description>Embark on an exciting adventure in Hawaii beaches!
</description>
<destination>Hawaii, USA</destination>
<price>4000</price>
<duration>10</duration>
<payment>
<EMIoption>no</EMIoption>
<refund>no</refund>
</payment>
</package>
<package id='Italian Getaway'>
<description>Indulge in the beauty and charm of Italy and get an all-
inclusive authentic Italian food tour!</description>
<destination>Italy</destination>
<price>2000</price>
<duration>8</duration>
<payment>
<EMIoption>yes</EMIoption>
<refund>no</refund>
</payment>
</package>
<package id='Andaman Island Retreat'>
<description>Experience the beauty of Island beaches,inclusive scuba
diving and Night kayaking through mangroves.</description>
<destination>Andaman and Nicobar Islands</destination>
<price>800</price>
<duration>8</duration>
<payment>
<EMIoption>no</EMIoption>
<refund>yes</refund>
</payment>
</package>
</travelPackages>

Plik zawiera dane 4 pakietów wycieczek, ze szczegółami miejsca docelowego, opisem, ceną i opcjami płatności dostarczonymi przez agencję. Przyjrzyjmy się podziałowi różnych części powyższego kodu XML:

  • Pierwiastek: Element najwyższego poziomu jest określany jako korzeń, czyli w naszym pliku. Zawiera wszystkie pozostałe elementy (różne oferowane wycieczki)
  • Atrybut: „id” jest atrybutem każdego z nich element w naszym pliku. Pamiętaj, że atrybut musi mieć unikalne wartości („wakacje w Paryżu”, „przygoda na Hawajach” itp.) dla każdego elementu. Atrybut i jego wartość są zwykle wymienione w tagu początkowym, jak widać.
  • Elementy potomne: Elementy zawinięte wewnątrz katalogu głównego są elementami potomnymi. W naszym przypadku wszystkie   tagi to elementy podrzędne, z których każdy przechowuje szczegółowe informacje o pakiecie wycieczki.
  • Elementy podrzędne: Element potomny może mieć więcej elementów podrzędnych w swojej strukturze. The element potomny ma elementy podrzędne , , , i . Zaletą XML jest to, że umożliwia on przechowywanie informacji hierarchicznych poprzez wiele zagnieżdżonych elementów. The element podrzędny ma ponadto elementy podrzędne I, które wskazują, czy dany pakiet ma opcję „zapłać przez EMI” i zwrot pieniędzy, czy nie.

Porada: Możesz utworzyć widok drzewa pliku XML, aby uzyskać jasne zrozumienie korzystania z niego narzędzie. Sprawdź hierarchiczny widok drzewa naszego pliku XML!

Jak analizować pliki XML za pomocą Pythona? Inteligencja danych PlatoBlockchain. Wyszukiwanie pionowe. AI.

Świetnie! Chcemy odczytywać dane zapisane w tych polach, wyszukiwać, aktualizować i wprowadzać zmiany zgodnie z potrzebami serwisu, prawda? Nazywa się to parsowaniem, w którym dane XML są dzielone na części i identyfikowane są różne części.

Istnieje wiele sposobów analizowania pliku XML w Pythonie z różnymi bibliotekami. Zanurzmy się w pierwszą metodę!


Wypróbuj Nanonets do analizowania plików XML. Rozpocznij bezpłatny okres próbny bez żadnych danych karty kredytowej.


Używanie Mini DOM do analizowania plików XML

Jestem pewien, że zetknąłbyś się z DOM (Document Object Model), standardowym interfejsem API do reprezentowania plików XML. Mini DOM to wbudowany moduł Pythona, który minimalnie implementuje DOM.  

Jak działa mini DOM?

Ładuje wejściowy plik XML do pamięci, tworząc podobną do drzewa strukturę „Drzewo DOM” do przechowywania elementów, atrybutów i treści tekstowych. Ponieważ pliki XML mają z natury hierarchiczną strukturę drzewa, ta metoda jest wygodna w nawigacji i wyszukiwaniu informacji.

Zobaczmy, jak zaimportować pakiet z poniższym kodem. Możesz przeanalizować plik XML za pomocą xml.dom.minidom.parse() funkcję, a także uzyskać element główny.

import xml.dom.minidom
# parse the XML file
xml_doc = xml.dom.minidom.parse('travel_pckgs.xml')
# get the root element
root = xml_doc.documentElement
print('Root is',root)

Dane wyjściowe, które otrzymałem dla powyższego kodu, to:

>> Root is <DOM Element: travelPackages at 0x7f05824a0280>

Powiedzmy, że chcę wydrukować miejsce, czas trwania i cenę każdej paczki.  

Połączenia pobierzAtrybut() Funkcja może służyć do pobierania wartości atrybutu elementu.

Jeśli chcesz uzyskać dostęp do wszystkich elementów w ramach określonego tagu, użyj metody getElementsByTagName()  metodę i podaj tag jako dane wejściowe. Najlepsze jest to, że metody getElementsByTagName() można używać rekurencyjnie do wyodrębniania zagnieżdżonych elementów.

# get all the package elements
packages = xml_doc.getElementsByTagName('package')
# loop through the packages and extract the data
for package in packages:
package_id = package.getAttribute('id')
description = package.getElementsByTagName('description')[0].childNodes[0].data
price = package.getElementsByTagName('price')[0].childNodes[0].data
duration = package.getElementsByTagName('duration')[0].childNodes[0].data
print('Package ID:', package_id)
print('Description:', description)
print('Price:', price)

Wyjście powyższego kodu jest pokazane tutaj, wraz z wyodrębnionym i wydrukowanym identyfikatorem, tekstem opisu i ceną każdego pakietu.

Package ID: Paris vacation
Description: Experience the magnificent beauty of Paris and the french culture.
Price: 3000
Package ID: Hawaii Adventure
Description: Embark on an exciting adventure in Hawaii beaches!
Price: 4000
Package ID: Italian Getaway
Description: Indulge in the beauty and charm of Italy and get an all-inclusive authentic Italian food tour!
Price: 2000
Package ID: Andaman Island Retreat
Description: Experience the beauty of Island beaches,inclusive scuba
diving and Night kayaking through mangroves.
Price: 800

Parser Minidom pozwala nam także przechodzić przez drzewo DOM od jednego elementu do jego elementu nadrzędnego, jego pierwszego elementu potomnego, ostatniego elementu potomnego i tak dalej. Możesz uzyskać dostęp do pierwszego elementu podrzędnego element za pomocą pierworodny atrybut. Można również wydrukować nazwę węzła i wartość wyodrębnionego elementu podrzędnego Nazwa węzła i wartość węzła atrybuty, jak pokazano poniżej.

# get the first package element
paris_package = xml_doc.getElementsByTagName('package')[0]
# get the first child of the package element
first_child = paris_package.firstChild
#print(first_child)
>>
<DOM Element: description at 0x7f2e4800d9d0>
Node Name: description
Node Value: None

Możesz sprawdzić, czy „opis” jest pierwszym elementem podrzędnym elementu . Istnieje również atrybut o nazwie węzły potomne który zwróci wszystkie elementy potomne obecne w bieżącym węźle. Sprawdź poniższy przykład i jego dane wyjściowe.

child_elements=paris_package.childNodes
print(child_elements)
>>
[<DOM Element: description at 0x7f057938e940>, <DOM Element: destination at 0x7f057938e9d0>, <DOM Element: price at 0x7f057938ea60>, <DOM Element: duration at 0x7f057938eaf0>, <DOM Element: payment at 0x7f057938eb80>]

Podobnie do tego, minidom zapewnia więcej sposobów przechodzenia, takich jak parentNode, lastChild nextSibling itp. Możesz sprawdzić wszystkie dostępne funkcje biblioteki tutaj.

Jednak główną wadą tej metody jest kosztowne użycie pamięci, ponieważ cały plik jest ładowany do pamięci. Używanie minidom dla dużych plików jest niepraktyczne. 


Zautomatyzuj parsowanie XML Nanonets. Rozpocznij bezpłatny okres próbny już dziś. Karta kredytowa nie jest wymagana.


Używanie biblioteki ElementTree do analizowania plików XML

ElementTree to szeroko stosowany wbudowany parser Pythona, który zapewnia wiele funkcji do czytania, manipulowania i modyfikowania plików XML. Ten parser tworzy strukturę przypominającą drzewo do przechowywania danych w formacie hierarchicznym.

Zacznijmy od zaimportowania biblioteki i wywołania funkcji parse() naszego pliku XML. Możesz także podać plik wejściowy w formacie łańcuchowym i użyć formatu z ciągu() funkcjonować. Po zainicjowaniu przeanalizowanego drzewa możemy użyć zdobądź roota () funkcję, aby pobrać tag główny, jak pokazano poniżej.

import xml.etree.ElementTree as ET
tree = ET.parse('travel_pckgs.xml')
#calling the root element
root = tree.getroot()
print("Root is",root)
Output:
>>
Root is <Element 'travelPackages' at 0x7f93531eaa40>

Główny tag „travelPackages” został wyodrębniony!

Powiedzmy, że teraz chcemy dostęp wszystkie pierwsze znaczniki podrzędne korzenia. Możemy użyć prostej pętli for i iterować po niej, wypisując znaczniki podrzędne, takie jak miejsce docelowe, cena itp. Zauważ, że gdybyśmy określili wartość atrybutu wewnątrz znacznika otwierającego opisu, nawiasy nie byłyby puste. Sprawdź poniższy fragment!

for x in root[0]:
print(x.tag, x.attrib)
Output:
>>
description {}
destination {}
price {}
duration {}
payment {}

Alternatywnie, iter () może pomóc w znalezieniu dowolnego interesującego elementu w całym drzewie. Użyjmy tego, aby wyodrębnić opisy każdego pakietu wycieczki w naszym pliku. Pamiętaj o użyciu tzw 'tekst' atrybut, aby wyodrębnić tekst elementu.

For x in root.iter('description'):
print(x.text)
Output:
>> "Experience the magnificent beauty of Paris and the french culture." "Embark on an exciting adventure in Hawaii beaches!" "Indulge in the beauty and charm of Italy and get an all-inclusive authentic Italian food tour!" "Experience the beauty of Island beaches,inclusive scuba diving and Night kayaking through mangroves.

Podczas korzystania z ElementTree podstawowa pętla for jest dość potężna, aby uzyskać dostęp do elementów potomnych. Zobaczmy jak.

Analizowanie plików XML za pomocą pętli for

Możesz po prostu iterować elementy potomne za pomocą pętli for, wyodrębniając atrybuty, jak pokazano poniżej.

for tour in root:
print(tour.attrib)
Output:
>>
{'id': 'Paris vacation'}
{'id': 'Hawaii Adventure'}
{'id': 'Italian Getaway'}
{'id': 'Andaman Island Retreat'}

Aby obsłużyć złożone zapytania i filtrowanie, ElementTee ma Znajdź wszystko() metoda. Ta metoda umożliwia dostęp do wszystkich elementów podrzędnych tagu przekazanego jako parametry. Powiedzmy, że chcesz poznać pakiety wycieczek poniżej 4000 USD, a także mieć opcję EMI jako „tak”. Sprawdź fragment.

for package in root.findall('package'):
price = int(package.find('price').text)
refund = package.find('payment/refund').text.strip("'")
if price < 4000 and refund == 'yes':
print(package.attrib['id'])

Zasadniczo iterujemy pakiety za pomocą root.findall('package'), a następnie wyodrębniamy cenę i zwracamy pieniądze za pomocą odnaleźć() metoda. Następnie sprawdzamy ograniczenia i odfiltrowujemy kwalifikowane pakiety, które są wydrukowane poniżej.

Wyjście:

>>

Paryskie wakacje

Rekolekcje na wyspie Andaman

Korzystając z ElementTree, możesz łatwo modyfikować i aktualizować elementy i wartości pliku XML, w przeciwieństwie do miniDOM i SAX. Sprawdźmy jak w następnej sekcji.

Jak modyfikować pliki XML za pomocą ElementTree?

Powiedzmy, że nadszedł czas na święta Bożego Narodzenia, a agencja chce podwoić koszty przesyłki. ElementTree zapewnia zestaw() funkcja, której możemy użyć aktualizacja wartości elementów. W poniższym kodzie uzyskałem dostęp do ceny każdego pakietu za pomocą funkcji iter() i manipulowałem cenami. Możesz użyć funkcji write(), aby napisać nowy plik XML ze zaktualizowanymi elementami.

for price in root.iter('price'):
new_price = int(price.text)*2
price.text = str(new_price)
price.set('updated', 'yes')
tree.write('christmas_packages.xml')

Powinieneś być w stanie znaleźć plik wyjściowy, taki jak ten na poniższym obrazku. Jeśli pamiętasz, ceny Paris Vacation i Hawaii Adventure to 3000 $ i 4000 $ w oryginalnym pliku.

Jak analizować pliki XML za pomocą Pythona? Inteligencja danych PlatoBlockchain. Wyszukiwanie pionowe. AI.

Ale co, jeśli chcemy dodać nowy tag do pakietu Andaman, aby zaznaczyć, że oferowany pobyt to „prywatna willa premium”. The Element podrzędny() pozwala nam na to funkcja ElementTree dodaj nowe podtagi według potrzeb, jak pokazano w poniższym fragmencie. Powinieneś przekazać element, który chcesz zmodyfikować, oraz nowy tag jako parametry do funkcji.

ET.SubElement(root[3], 'stay')
for x in root.iter('stay'):
resort = 'Premium Private Villa'
x.text = str(resort)
Jak analizować pliki XML za pomocą Pythona? Inteligencja danych PlatoBlockchain. Wyszukiwanie pionowe. AI.

Mam nadzieję, że wyniki też masz! Pakiet zapewnia również Muzyka pop() funkcja, dzięki której możesz usunąć atrybuty i podelementy, jeśli są niepotrzebne.


Proste API dla XML (SAX)

SAX to kolejny parser Pythona, który pokonuje wady miniDOM, czytając dokument sekwencyjnie. Nie ładuje całego drzewa do swojej pamięci, a także pozwala odrzucić elementy, zmniejszając zużycie pamięci.

Najpierw utwórzmy obiekt parsera SAX i zarejestrujmy funkcje zwrotne dla różnych zdarzeń, które chcesz obsłużyć w dokumencie XML. Aby to zrobić, definiuję niestandardową klasę TravelPackageHandler, jak pokazano poniżej, dzieląc podklasę ContentHandler SAX-a.

import xml.sax
# Define a custom SAX ContentHandler class to handle events
class TravelPackageHandler(xml.sax.ContentHandler):
def __init__(self):
self.packages = []
self.current_package = {}
self.current_element = ""
self.current_payment = {} def startElement(self, name, attrs):
self.current_element = name
if name == "package":
self.current_package = {"id": attrs.getValue("id")} def characters(self, content):
if self.current_element in ["description", "destination", "price", "duration", "EMIoption", "refund"]:
self.current_package[self.current_element] = content.strip()
if self.current_element == "payment":
self.current_payment = {} def endElement(self, name):
if name == "package":
self.current_package["payment"] = self.current_payment
self.packages.append(self.current_package)
if name == "payment":
self.current_package["payment"] = self.current_payment def startElementNS(self, name, qname, attrs):
pass def endElementNS(self, name, qname):
pass

W powyższym fragmencie, startElement(), znaki(), i element końcowy() metody są używane do wyodrębniania danych z elementów i atrybutów XML. Gdy parser SAX czyta dokument, uruchamia zarejestrowane funkcje wywołania zwrotnego dla każdego napotkanego zdarzenia. Na przykład, jeśli napotka początek nowego elementu, wywołuje funkcję startElement(). Teraz użyjmy naszego niestandardowego modułu obsługi, aby uzyskać różne identyfikatory pakietów, analizując nasz przykładowy plik XML.

# Create a SAX parser object
parser = xml.sax.make_parser()
handler = TravelPackageHandler()
parser.setContentHandler(handler)
parser.parse("travel_pckgs.xml")
for package in handler.packages:
print(f'Package: {package["id"]}')

Wyjście >>

Pakiet: wakacje w Paryżu

Pakiet: Hawajska przygoda

Pakiet: Włoski wypad

Pakiet: Rekolekcje na Andamanach

SAX może być używany do dużych plików i przesyłania strumieniowego ze względu na swoją wydajność. Jest to jednak niewygodne podczas pracy z głęboko zagnieżdżonymi elementami. Co jeśli chcesz uzyskać dostęp do dowolnego losowego węzła drzewa? Ponieważ nie obsługuje losowego dostępu, parser będzie musiał kolejno czytać cały dokument, aby uzyskać dostęp do określonego elementu.


Synchronizuj wszystkie swoje podwójne wpisy z Nanonets. Dbaj o równowagę wszystkich kont, 24 godziny na dobę, 7 dni w tygodniu. Skonfiguruj swoje procesy księgowe w <15 minut. Zobacz jak.


Streaming Pull Parser dla XML

To jest ciągnięcie Biblioteka Pythona, która udostępnia interfejs API parsera przesyłania strumieniowego z interfejsem podobnym do DOM.

Jak to działa?

Przetwarza dane XML w sposób „pull”. Oznacza to, że wyraźnie żądasz od parsera dostarczenia następnego zdarzenia (np. elementu początkowego, elementu końcowego, tekstu itp.) w danych XML.

Składnia jest znana z poprzednich bibliotek. W poniższym kodzie demonstruję, jak zaimportować bibliotekę i użyć jej do wydrukowania wycieczek, które trwają 4 dni lub dłużej, a także zapewnić zwrot pieniędzy w przypadku anulowania.

from xml.dom.pulldom import parse
events = parse("travel_pckgs.xml")
for event, node in events:
if event == pulldom.START_ELEMENT and node.tagName == 'package':
duration = int(node.getElementsByTagName('duration')[0].firstChild.data)
refund = node.getElementsByTagName('refund')[0].firstChild.data.strip("'")
if duration > 4 and refund == 'yes':
print(f"Package: {node.getAttribute('id')}")
print(f"Duration: {duration}")
print(f"Refund: {refund}")

Powinieneś otrzymać dane wyjściowe takie jak:

Pakiet: wakacje w Paryżu

Czas trwania: 7

Zwrot pieniędzy: tak

Pakiet: Rekolekcje na Andamanach

Czas trwania: 8

Zwrot pieniędzy: tak

Sprawdź wyniki! Parser pull łączy w sobie kilka funkcji z miniDOM i SAX, dzięki czemu jest stosunkowo wydajny.

Podsumowanie

Jestem pewien, że już dobrze znasz różne parsery dostępne w Pythonie. Równie ważna jest wiedza, kiedy wybrać parser, aby zaoszczędzić czas i zasoby. Spośród wszystkich parserów, które widzieliśmy, ElementTree zapewnia maksymalną kompatybilność z wyrażeniami XPath, które pomagają wykonywać złożone zapytania. Minidom ma łatwy w użyciu interfejs i może być wybrany do obsługi małych plików, ale jest zbyt wolny w przypadku dużych plików. Jednocześnie SAX jest używany w sytuacjach, w których plik XML jest stale aktualizowany, jak w przypadku uczenia maszynowego w czasie rzeczywistym.

Alternatywą do analizowania plików jest użycie narzędzi do automatycznego analizowania, takich jak Nanonets. Nanonets może pomóc w wyodrębnieniu danych z dowolnego rodzaju dokumentu w ciągu kilku sekund bez pisania ani jednej linijki kodu.

Ozoptymalizuj wyniki swojej firmy, zmniejsz koszty i przyspiesz wzrost. Dowiedzieć się jak przypadki użycia Nanonets mogą odnosić się do Twojego produktu.


Znak czasu:

Więcej z AI i uczenie maszynowe