PCkurier 25 perl


PCkurier 25/2001 >> DLA PRAKTYKÓW >> KURSY
XML w języku Perl
Tam i z powrotem
Autor: Maciej Koziński
Extensible Markup Language (XML) staje się coraz bardziej popularnym narzędziem
reprezentowania danych. Język Perl ma zarówno wbudowane mechanizmy, jak i moduły
rozszerzeń, ułatwiające stosowanie XML. Przedstawiamy niektóre z nich.
Extensible Markup Language
XML jest uproszczoną wersją SGML (Standarized General Markup Language), rozwijaną przez World Wide Web Consortium.
Celem tej specyfikacji jest m.in. rozszerzenie możliwości WWW poprzez dostarczenie elastycznych mechanizmów opisu danych.
XML jest metajęzykiem opisu danych i innych języków (np. Wireless Markup Language stosowany w WAP). Nie stanowi on
stałego podzbioru elementów, jak HTML, dzięli czemu daje użytkownikowi możliwość tworzenia nowych formatów dokumentów.
Pozwala na tworzenie własnych struktur danych, niezależnych od platformy programowej oraz definiowanie własnych
znaczników. Nie opisuje sposobu prezentacji danych - niezbędne jest stosowanie innych technologii (np. CSS czy związanego z
XML eXtended Stylesheet Language - XSL). Elastyczność pozwala zarazem uniknąć problemów pojawiających się w rozwoju
HTML - niezgodności poszczególnych elementów w implementacjach narzędzi różnych producentów. Założenia projektowe XML
obejmowały m.in.:
- łatwość stosowania w Internecie,
- możliwość zastosowania w aplikacjach różnego typu,
- zgodność z SGML,
- łatwość obsługi ze strony programisty i tworzenia aplikacji,
- zminimalizowanie opcjonalnych własności języka,
- czytelność dla użytkownika, bez konieczności posiadania wyspecjalizowanych narzędzi,
- łatwość tworzenia dokumentów,
- szybkość rozwoju standardu.
XML może reprezentować dane różnego typu - w odróżnieniu od HTML, nie opisującego danych, a jedynie strukturę i
(częściowo) sposób prezentacji dokumentu. Spektrum potencjalnych zastosowań XML jest niezwykle szerokie. Można z jego
pomocą opisać np. dane muzyczne, chemiczne, genealogiczne, historyczne, inżynierskie, finansowe, grafikę wektorową,
równania matematyczne i wiele innych danych o bogatej, złożonej strukturze. Spore nadzieje wiąże się z zastosowaniem XML do
elektronicznej wymiany dokumentów.
O wzroście zainteresowania XML jako użytecznym narzędziem zapisu danych świadczy jego wykorzystanie w
najnowszych pakietach biurowych (np. w testowej wersji Open Office 6.0). Niewątpliwie zastosowanie
jednolitego, elastycznego i otwartego formatu reprezentacji danych ułatwi ich wymianę między aplikacjami i
organizacjami.
Do skorzystania z dobrodziejstw XML niezbędne jest posiadanie odpowiednich narzędzi do konwersji z najczęściej
dotychczas używanych formatów. Archiwum CPAN zawiera wiele modułów języka Perl, realizujących konwersję
danych do i z XML. Wielość tych narzędzi, prostota ich pozyskania i użytkowania, a przede wszystkim łatwy
dostęp do tworzonych w pamięci operacyjnej złożonych struktur danych, odpowiadających zapisom w pliku XML
to niewątpliwe zalety Perla przy współpracy z XML.
Nauka czytania...
Nim zajmiemy się konwersją znanych formatów danych do XML, przyjrzyjmy się przenoszeniu danych pomiędzy
XML a strukturami Perla. Budowa odpowiednio złożonych drzew, a zwłaszcza dostęp do poszczególnych
elementów są w Perlu proste. Wystarczy wskazać początek drzewa i poszczególne wskazniki, by dojść do
wybranego elementu. Nie wymaga to pisania złożonych, rekurencyjnych procedur wyszukujących, jak np. w
języku C - wystarczy umiejętność posługiwania się odpowiednimi operatorami.
Aby odczytać dane z pliku XML i umieścić je w odpowiedniej strukturze, można np. napisać własny analizator
składni oraz podprogram zarządzający drzewami danych w pamięci. Byłoby to jednak wyważanie otwartych drzwi,
ponieważ jest wiele modułów implementujących to na różne sposoby. Jednym z nich jest XML::Parser - ten moduł
analizatora składni XML jest perlową nakładką na bibliotekę Expat (przeznaczoną dla języka C) i jednym z
pierwszych modułów Perla przeznaczonych do przetwarzania XML. Korzystanie z niego jest jednak dużo mniej
komfortowe niż z nowszych narzędzi perlowych. Pokażemy więc tylko jeden, ograniczony do minimum przykład
jego zastosowania, niezbędny do skorzystania z modułu XML::SimpleObject. Dostęp do danych nie jest wygodny -
trzeba tworzyć specjalne procedury wywoływane w reakcji na zdarzenia (handlers). Poniższy program tworzy
nowy obiekt XML::Parser, po czym wywołuje metodę przeprowadzającą analizę składniową wskazanego pliku:
use XML::Parser;
$f = "./znajomi.xml";
$p = XML::Parser->new();
$p->parsefile ($f);
Pozyskanie danych z XML do wewnętrznych struktur Perla jest znacznie przyjemniejsze przy wykorzystaniu
modułu XML::Simple. Utworzone w pliku XML drzewiaste struktury danych znajdują odzwierciedlenie w tablicy
zawierającej odwołania do kolejnych węzłów drzewa. Taka wewnętrzna reprezentacja pozwala na proste
odwoływanie się do poszczególnych elementów poprzez kolejne wskazania. Nie jest konieczne pisanie złożonych
procedur do "wędrówki" po węzłach drzewa. Dostęp do kolejnych elementów możemy uzyskać, korzystając na
odpowiednim poziomie drzewa z instrukcji wyliczenia:
foreach $k (keys (%{$xml->{znajomi}}))
Przyjrzyjmy się w praktyce strukturom danych tworzonych w wyniku przetworzenia pliku XML za pomocą modułu
XML::Simple. Rozpatrzmy plik XML o nazwie znajomi.xml (patrz wydruk 1 ). Dane z tego pliku możemy wczytać
do tablic asocjacyjnych Perla w następujący sposób:
use XML::Simple;
my $file = './znajomi.xml';
my $xs1 = XML::Simple->new();
my $doc = $xs1->XMLin($file);
Utworzenie obiektu XML::Simple i skorzystanie z jego metody XMLin(nazwapliku) tworzy w pamięci tablicę
zawierającą odwołania do drzew reprezentujących już konkretne elementy pliku XML, do których możemy
odwołać się bezpośrednio, używając rozwlekłego zapisu:
print $doc->{osoba}->{nazwisko};
lub
print $doc->{osoba}->{wyglad}->{wzrost};
Całość utworzonej w pamięci struktury danych możemy obejrzeć, korzystając z modułu Data::Dumper:
use Data::Dumper;
print Dumper ($doc);
Innym ciekawym sposobem reprezentowania danych XML jest przekształcenie ich do postaci obiektów języka Perl.
Umożliwia to moduł XML::SimpleObject. Do zainicjowania obiektu niezbędny będzie moduł XML::Parser - drzewo
skonstruowane w wyniku jego działania zostanie przekształcone w obiekt.
Obiekt powołany do życia przez XML:: SimpleObject zawiera kilka metod udostępniających dalsze gałęzie drzewa
lub listy ich nazw. Poszczególne elementy są identyfikowane nazwami (ciągami znaków), podobnie jak w
znacznikach XML. Istnieją również metody udostępniające atrybuty elementu lub jego wartość:
" child (nazwa) - odwołanie do obiektu o wymienionej nazwie,
" children (nazwa) - odwołanie do tablicy obiektów elementu wymienionego jako argument; wywołanie
tej metody w wyliczeniu foreach zapewnia programowi dostęp do poszczególnych elementów, ich
atrybutów i wartości,
" attribute (nazwa) - zwraca wartość atrybutu danego obiektu o nazwie podanej jako argument,
" value - zwraca wartość wskazanego elementu,
" attributes - zwraca odwołanie do tablicy asocjacyjnej atrybutów wskazanego elementu,
" children_names - zwraca odwołanie do tablicy nazw elementów potomnych wskazanego elementu.
A oto praktyczny przykład użycia modułu XML::SimpleObject do stworzenia obiektowej reprezentacji danych XML.
Rozważmy przykład z plikiem znajomi.xml. Utworzenie obiektu reprezentującego dane z tego pliku oraz
mechanizmy dostępu do nich przedstawia wydruk 2 .
Tworzymy nowy obiekt analizatora składni XML::Parser z atrybutem Style o wartości Tree. Opcja ta wyznacza typ
danych zwracanych przez analizator składni (poszczególne style i metody ich rozbudowy są opisane w
dokumentacji systemowej modułu). Dane z analizatora składni są przekazane nowo tworzonemu obiektowi
XML::SimpleObject.
...i pisania
Okazuje się, że łatwiej jest odczytać plik XML i utworzyć z danych struktury w pamięci operacyjnej, niż
przeprowadzić operację odwrotną. Korzystając z modułu XML::Simple, możemy także zapisać "drzewiastą"
strukturę danych do pliku XML, jednak z ograniczeniami. Mechanizmy modułu nie umożliwiają wyboru pomiędzy
zapisaniem pewnej porcji danych jako elementu XML lub jako atrybutu tegoż elementu - podobne ograniczenia
napotkamy przy odczycie plików XML, co zawęża użyteczność tego modułu do prostych danych, nie zawierających
atrybutów. Sposób zapisu przy użyciu XML:: Simple demonstruje program na wydruku 3 .
Ograniczenia modułu XML::Simple można oczywiście w prosty sposób obejść, stosując moduł XML::Writer.
Umożliwia on ingerencję w sposób zapisu danych w pliku XML nawet na elementarnym poziomie znaczników XML,
ale kosztem łatwości korzystania z mechanizmu zapisu - programista musi sam dokładnie określić, co i w jaki
sposób ma zostać zapisane. Pozwala to dokonywać zapisów w sposób dość dowolny - nie musimy bowiem
uporządkować tablicy asocjacyjnej z danymi do zapisu dokładnie w taki sposób, w jaki będzie zapisana w pliku
XML. Możemy manipulować danymi nawet na etapie zapisywania ich do pliku.
Przykładowy zapis złożonej, wielopoziomowej tablicy asocjacyjnej do pliku XML, przy użyciu modułu XML::Writer
przedstawia wydruk 4 .
Na tym wydruku znacznik o nazwie "osoba" zostaje zainicjowany metodą StartTag z atrybutem "nazwisko",
wybranym z pola "nazwisko" obecnie przetwarzanego rekordu. Mechanizm ten będzie z pewnością użyteczny przy
konwersji dokumentów XML do HTML, gdzie poszczególne znaczniki mają swoje atrybuty przy odwołaniach, dla
takiego np. adresu URL:
Rozdzia" 1
Zapisanie danych w postaci HTML może wyglądać tak, jak na wydruku 5 .
Podobnie wyglądać będzie zapis dla odsyłaczy . Moduł XML::Writer będzie niezbędny, jeśli zechcemy
zapisać dane w postaci HTML tam, gdzie wystąpią zagnieżdżone elementy mające własne atrybuty, np. odsyłacz
znajdzie się wewnątrz odsyłacza .
Dane wyjściowe z XML::Writer kierowane są do pliku standardowego wyjścia. Możemy to zmienić, korzystając z
modułu IO::File:
use XML::Writer;
use IO;
my $output = new IO::File(">output.xml");
my $writer = new XML::Writer(OUTPUT => $output);
...
$output->close();
Moduł XML::SimpleObjects nie udostępnia mechanizmów zapisu danych do pliku - w tym celu należy skorzystać z
modułów XML::Simple i XML::Writer.
Konwersja na całego
Skoro umiemy już przenosić informacje między strukturami danych Perla a XML, możemy spróbować przenieść do
XML dane z popularnych formatów, np. z CSV. Dane tabelaryczne zgromadzone w najprostszym formacie -
kolumn podzielonych separatorem - możemy łatwo przekształcić do postaci XML przy użyciu modułu XML::CSV.
Do poprawnej pracy wymaga on modułu Text::CSV_XS. Jest on odpowiedzialny za właściwy "rozbiór" pliku CSV,
natomiast jego funkcjonowanie ukryte jest za interfejsem XML::CSV. Przykład pliku CSV o nazwie znajomi.csv
zawiera wydruk 6 .
Tworzymy nowy obiekt ze wskazaniem column_headings na łańcuch zawierający nagłówki kolumn, które w
trakcie konwersji zostaną zamienione na nazwy elementów. Za pomocą column_data można też wskazać
dwuwymiarową tablicę zawierającą dane. Metoda parse_doc() wczytuje i przetwarza podany jako parametr plik
CSV. Możemy też zadeklarować pobranie nazw kolumn (i przyszłych elementów XML) z danego wiersza pliku CSV:
my $csv = XML::CSV->new({column_headings =>
$csv->parse_doc("in_file.csv", {headings => 1});
Metoda print_xml wpisze treść XML do pliku o podanej nazwie, z głównym znacznikiem file_tag oraz znacznikiem
oddzielającym poszczególne rekordy parent_tag. Wynik działania programu na danych z pliku znajomi.csv
przedstawia wydruk 7 .
Większość popularnych aplikacji jest w stanie zapisać dane tabelaryczne w formacie CSV. W module XML::CSV
mamy więc narzędzie zdolne przekształcić dane z wielu aplikacji do postaci XML. Komu droga przez CSV wyda się
zbyt długa, może skorzystać ze specjalizowanych modułów. Jednym z nich jest XML::Excel, który jest podobny do
obiektu XML::CSV - jest inicjowany w ten sam sposób, ma identyczne pola i metody. Sposób korzystania z niego
jest taki sam, za wyjątkiem oczywiście zródła danych - musi być to arkusz kalkulacyjny Excela.
Baza do XML
Zajrzyj
- www.w3.org/TR/REC-xml - drugie wydanie specyfikacji XML 1.0
- www.xml.com - XML i technologie pokrewne - podręczniki, informacje, narzędzia
- www.xmlpitstop.com - pomoc przy korzystaniu z technologii XML, informacje, zasoby programowe i odsyłacze
- www.zvon.org - przewodniki i narzędzia dla programistów i webmasterów korzystających z XML
- www.xmlsoftware.com - zbiór informacji i odsyłacze do oprogramowania przetwarzającego XML
- www.ucc.ie/xml - zbiór pytań i odpowiedzi (FAQ) na temat XML
- www.garshol.priv.no/download/xmltools - zbiór odsyłaczy do bezpłatnie udostępnianych narzędzi i oprogramowania
związanego z technologią XML
- xmlsoft.org/xml.html - biblioteka XML dla środowiska GNOME
- www.jclark.com/xml - zestaw odsyłaczy do narzędzi przetwarzania XML
- www.jclark.com/xml/expat.html - strona biblioteki języka C Expat - XML Parser Toolkit
- www.spiderpro.com/bu/buxmlm001.html - Kick-start XML - przewodnik po XML dla początkujących
- www.rpbourret.com/xmldbms/index.htm - biblioteka middleware zapewniająca wymianę danych między relacyjnymi
bazami danych a XML z poziomu Javy i Perla
- www.perl.com - język Perl - zasoby, artykuły, przewodniki
Najbardziej intrygującym zagadnieniem będzie przeniesienie informacji z systemów zarządzania relacyjnymi
bazami danych do XML. Elastyczność zapytań SQL, możliwość reprezentowania ich wyników w formacie XML
dostępnym dla innych aplikacji niewątpliwie kusi programistów. A jest o co powalczyć - jak widać, nie jest to takie
trudne, jeśli skorzystamy z modułu DBIx::XML_RDB. Umożliwia on zadanie zapytania w języku SQL do systemu
bazodanowego i zapisanie jego wyników w formacie XML, w dodatku czyni to w sposób mało skomplikowany
(patrz wydruk 8 ).
Tworzymy obiekt DBIx::XML_RDB, podając jako parametr ciąg identyfikujący odpowiedni sterownik silnika
bazodanowego oraz bazę danych i serwer - dla obiektu DBI - a także sterownik, nazwę użytkownika i hasło.
Metoda DoSql wykonuje podane zapytanie SQL, którego treść jest konwertowana do postaci XML i zachowywana
w polu GetData. Stamtąd możemy przepisać ją w dowolne miejsce, np. do pliku - jak w naszym przykładzie -
najprostszą funkcją "print". Przy składowaniu w tabeli "ksiazka_adresowa" danych, sformułowanych analogicznie
jak w przykładzie z tabelą CSV, zawartość pliku adresy.xml wyglądać będzie jak na wydruku 9 .
Operacja odwrotna nie doczekała się własnego modułu - poniekąd słusznie, ponieważ przekształcenie danych
reprezentowanych w XML jako drzewo do postaci tabel relacyjnej bazy danych nie jest zadaniem dającym się
łatwo zautomatyzować. Każdy przypadek wymagać będzie zaprojektowania specjalnej bazy, osobnego rozkładu
drzewa na poszczególne elementy i przydzielenia ich do poszczególnych tabel. Stąd tylko część tego zadania - a
więc stworzenie wewnętrznych struktur danych z pliku XML - można powierzyć opisanym w artykule modułom.
* * *
Przedstawione tu sposoby przenoszenia danych pomiędzy XML a innymi formatami danych pokazują jedynie
ułamek możliwości tkwiących w tym metajęzyku. XML ze swoją elastycznością i prostotą świetnie komponuje się z
mechanizmami Perla - zwłaszcza z jego łatwością dostępu do złożonych struktur danych w pamięci, a wiele
modułów rozszerzeń Perla ułatwia zastosowanie XML w interakcji z różnymi aplikacjami i środowiskami.


Wyszukiwarka