Ten post jest krótką, ale praktyczną demonstracją sprawdzania poprawności dokumentu XML względem plików „Definicja typu dokumentu” (DTD) i „Definicja schematu XML” (XSD). Taka weryfikacja jest konieczna, aby mieć pewność, że kod XML przesyłany pomiędzy klientem a serwerem obsługującym usługę sieci Web opartą na formacie XML zostanie odebrany zgodnie z oczekiwaniami. Zarówno DTD, jak i XSD umożliwiają zdefiniowanie elementów i atrybutów, jakie powinien zawierać dokument XML. XSD ma tę zaletę, że jest napisany w formacie XML, co ułatwia jego czytanie. XSD umożliwia także zdefiniowanie większej ilości informacji o elemencie — takich jak typ danych, przestrzeń nazw i ograniczenia dotyczące wartości. Istnieje kilka modułów do sprawdzania poprawności XML w Perlu 5, ale ja użyję dwóch z przestrzeni nazw Lib::XML.
Konfiguracja projektu
Pliki projektu
Będę używać następujących plików znajdujących się w katalogu o nazwie perl5-xml-validation
, aby zademonstrować walidację zarówno DTD, jak i XSD.
perl5-xml-validation/ . ├── bin │ ├── dtd_validation.pl │ └── xsd_validation.pl ├── cpanfile └── xml ├── book.xml └── schemas ├── book.dtd └── book.xsd
Po utworzeniu katalogu pamiętaj o wprowadzeniu go za pomocą cd perl5-xml-validation
.
Zależności
Otwórz plik cpanfile
i wypisz następujące moduły:
requires 'XML::LibXML'; requires 'Try::Tiny';
Uruchom cpanm -L local --installdeps .
, aby zainstalować moduły. Pozostałe pliki wyjaśnię, gdy zaczniemy z nich korzystać.
XML-a
Dokument XML użyty w tej demonstracji zawiera po prostu szczegóły książki w pliku ./xml/book.xml
w następujący sposób:
<?xml version="1.0" encoding="utf-8" ?> <book> <title>XML Validation</title> <numPages>-200</numPages> </book>
Wartość „-200” dla elementu numPages została ustawiona celowo. Powód powinien być jasny później.
Walidacja XML za pomocą DTD
Plik DTD
W pliku ./xml/schemas/book.dtd
znajdują się następujące definicje:
<!ELEMENT book (title,author,numPages?)> <!ELEMENT title (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT numPages (#PCDATA)>
Aby jakikolwiek dokument XML powiązany z tym DTD był ważny, musi zawierać elementy book, title, author i opcjonalnie numPages . Jak zauważysz, w zdefiniowanym wcześniej kodzie XML brakuje elementu author — poprawimy to później.
Teraz zweryfikujmy kod XML. Plik ./bin/dtd_validation.pl
zawiera następujący kod, który wyjaśnię poniżej.
Kodeks
#!/usr/bin/env perl use v5.18; use warnings; use XML::LibXML; use Try::Tiny qw(try catch); my $xml_doc = XML::LibXML->load_xml(location => './xml/book.xml'); my $dtd_doc = XML::LibXML::Dtd->new('', './xml/schemas/book.dtd'); my $is_xml_valid = try { $xml_doc->validate($dtd_doc) } catch { say '==> ' . $_; return 0; }; say $is_xml_valid ? 'Valid' : 'Invalid';
Jeśli chodzi o walidację, powyższy kod wykonuje następujące czynności:
- Ładuje plik XML za pomocą
load_xml
, co zwraca obiektXML::LibXML::Document
przypisany do$xml_doc
. - Następnie ładowany jest plik DTD
book.dtd
jako część konstrukcji instancji XML::LibXML::Dtd. - Na koniec sama walidacja odbywa się przy użyciu metody
validate
.
Aby wykonać trójskładnikowe wyrażenie na dole kodu, używamy funkcji try
i catch
, które są eksportowane przez Try::Tiny. Te dwie funkcje obsłużą wszelkie błędy zgłoszone przez metodę validate
. Brak obsługi błędów, które wystąpią podczas wywołania validate
spowoduje zatrzymanie wykonywania skryptu, w związku z czym operacja trójskładnikowa nie zostanie wykonana.
Błędy walidacyjne
Teraz, jeśli uruchomisz perl ./bin/dtd_validation.pl
i nie poprawiłeś wcześniej kodu XML, zauważysz podobne wyniki w powłoce, jak pokazano poniżej:
==> ./xml/book.xml:0: validity error : Element book content does not follow the DTD, expecting (title , author , numPages?), got (title numPages ) Invalid
Komunikat wyjściowy wskazuje, że elementy podrzędne elementu book
nie są zgodne z oczekiwaniami. Podczas walidacji oczekiwano title
, author
i opcjonalnie numPages
(w tej kolejności), ale zamiast tego otrzymano title
i numPages
.
Naprawianie błędu
Samo dodanie elementu author
tuż po elemencie title i przypisanie mu wartości, na przykład: <author>Johny Bravo</author>
, zapewni pomyślne sprawdzenie poprawności przy następnym uruchomieniu skryptu. W związku z tym zostanie wydrukowane Valid
.
Walidacja XML za pomocą XSD
Plik XSD
Plik ./xml/schemas/book.xsd
określa strukturę, jakiej powinien przestrzegać dokument ./xml/book.xml
w następujący sposób:
<?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="book"> <xs:complexType> <xs:sequence> <xs:element name = "title" type = "xs:string"/> <xs:element name = "author" type = "xs:string"/> <xs:element name = "numPages" type = "xs:positiveInteger" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Podobnie jak w zdefiniowanym wcześniej DTD, elementy title i author są obowiązkowe, a drugi numPages jest opcjonalny (oznaczany przez minOccurs="0"
). Należy również zauważyć, że oczekuje się, że wartość numPages
będzie typu positiveInteger
. XSD umożliwia definiowanie wielu różnych typów danych przy użyciu bogatszej składni, podczas gdy DTD tego nie robi.
Kodeks
Plik ./bin/xsd_validation.pl
zawiera następujący kod, który wyjaśniam poniżej:
#!/usr/bin/env perl use v5.18; use warnings; use XML::LibXML; use Try::Tiny qw(try catch); my $xml_doc = XML::LibXML->load_xml(location => './xml/book.xml'); my $xsd_doc = XML::LibXML::Schema->new(location => './xml/schemas/book.xsd'); my $is_xml_valid = try { not $xsd_doc->validate($xml_doc); } catch { say '==> ' . $_; return 0; }; say $is_xml_valid ? 'Valid' : 'Invalid';
Powyższy kod jest tym samym ogólnym procesem, co kod weryfikacyjny DTD przedstawiony wcześniej. Jedyne dwie różnice w implementacji to:
1) Moduł XML::LibXML::Schema służy zarówno do ładowania, jak i sprawdzania poprawności pliku XML.
2) Metoda XML::LibXML::Schema
validate
faktycznie zwraca 0
, gdy walidacja zakończy się pomyślnie. W związku z tym poprzedzam wywołanie ...validate($xml)
słowem kluczowym not
, aby jego fałszywa wartość zwracana była prawdziwa.
Błędy walidacyjne
Uruchom weryfikację XSD za pomocą perl ./bin/xsd_validation.pl
.
==> ./xml/book.xml:0: Schemas validity error : Element 'numPages': '-200' is not a valid value of the atomic type 'xs:positiveInteger'. Invalid
Uruchomienie skryptu powinno dać wynik widoczny powyżej. Błąd wskazuje, że XSD oczekuje dodatniej wartości całkowitej dla numPages, ale w rzeczywistości XML zawiera ujemną liczbę całkowitą, w tym przypadku „-200”.
Naprawianie błędu
Prawdopodobnie mnie ubiegłeś, ale sama zmiana wartości numPages
z -200 na 200 i ponowne uruchomienie skryptu powinna dać wynik Valid
.
Wniosek
Walidacja dokumentu XML przy użyciu dwóch omawianych modułów XML::LibXML wymagała jedynie dwóch obiektów, wywołania metody validate i użycia funkcji try i catch, aby obsłużyć wszelkie błędy, które mogą zostać zgłoszone.
Jeśli chcesz zobaczyć, jak weryfikacja została przeprowadzona przy użyciu testów Perla, kliknij tutaj, aby wyświetlić repozytorium Github zawierające kod tego artykułu.
Dziękujemy za przeczytanie tego artykułu! Możesz zostawić poklask👏 i polecić ten artykuł innym.