Einführung in Perl WWW, Teil 2: XML Jörn Clausen Georg Fuellen
Übersicht XML: extensible Markup Language XML parsen: XML::Parser SAX: Simple API for XML DOM: Document Object Model XPath XML erzeugen
die Ursprünge von XML HTML Markupsprache für das WWW Mischung aus Struktur- und Layout-Information proprietäre Erweiterungen, Mißbrauch von tags Informationen in HTML-Seiten verschüttet Lösung: Markup den Anforderungen anpassen Standard Generalized Markup Language (SGML) zu kompliziert XML: 1996/97 entwickelt, 1998 erste Recommendation des W3C inzwischen: zahlreiche Standards im XML-Umfeld
XML extensible Markup Language ist... keine Markupsprache nicht HTML++, sondern SGML kein Allheilmittel, trotz des Hypes ist aber auch... einfach zu erlernen weithin akzeptiert durch viele Implementierungen etabliert
ein Beispiel <?xml version="1.0"?> <library> <book edition="3rd" year="2000"> <title>programming Perl</title> <author>larry Wall</author> <author>tom Christiansen</author> <author>jon Orwant</author> </book> <book year="1998"> <title>advanced Perl Programming</title> <author>sriram Srinivasan</author> </book> </library>
Aufbau von XML: Elemente öffnendes und schließendes tag: <item>xml is not a...</item> keine Minimierungsregeln leeres Inhaltsmodell: <hr/> statt <hr></hr> statt <hr> Schachtelung muß passen : well-formed
Aufbau von XML: Attribute Zusatzinformationen zu Elementen <book year="2000">... </book> Attribute im öffnenden tag Design-Frage: Wann Element, wann Attribut? <date y="2001" m="7" d="9"/> vs. <date><y>2001</y><m>7</m><d>9</d></date>
Aufbau von XML: Entitäten Makros und Sonderzeichen in XML vordefiniert: & < > ' " weitere müssen definiert werden XML verwendet Unicode
Verwendung von XML Texte/Daten können ad-hoc kodiert werden stand-alone Dokument formale Grammatik: Document Type Definition (DTD) weitere Grammatik-Sprachen: XML-Schema, RELAX NG,... Dokument validiert
Verarbeitung von XML zwei Verfahren: event-basiert Baumstruktur Speicherplatz vs. freier Zugriff Geschwindigkeit vs. startup-zeit stream-fähigkeit
XML::Parser verwendet expat ist Grundlage für fast alle weiteren XML-Module handler für events, u.a.: Init, Final Start, End Char,... handler ist Subroutine, erhält geeignete Parameter
XML::Parser, cont. use XML::Parser; my $parser = XML::Parser->new( Handlers => { Start => \&start_h, End => \&end_h, Char => \&char_h }); $parser->parsefile( library.xml ); sub start_h { my ($parser, $elem, @attr) = @_; print "found $elem\n"; for (; $key=shift(@attr), $val=shift(@attr); ) { print " $key --> $val\n"; } }
SAX The Simple API for XML Java-API events: start_document, end_document, start_element, end_element, characters,... Trennung in Parser-Modul und Handler-Modul verschiedene SAX-Parser: XML::Parser::PerlSAX XML::SAX::Expat, XML::LibXML::SAX::Parser,... Parser-Factory Basis-Klasse für Handler: XML::SAX::Base
SAX, cont. handler-klasse kann von XML::SAX::Base erben package MyHandler; use XML::SAX::Base; @ISA = ( XML::SAX::Base ); sub start_element { my ($self, $data) = @_; my $element = $data->{name}; my $attref = $data->{attributes};... } vorgefertigte Module, z.b. XML::Handler::XMLWriter
SAX, cont. Verwaltung von SAX-Parsern durch XML::SAX XML::SAX::parsers liefert Liste von installierten Modulen Auswahl eines Parsers: my $handler = MyHandler->new; my $factory = XML::SAX::ParserFactory->new; my $sax = $factory->parser(handler => $handler); $sax->parse_uri($file); Anforderungen an Parser: $factory->require_feature(...) fallback: XML::SAX::PurePerl
DOM Document Object Model Repräsentation des XML-Dokuments als Baum Knoten des Baums: Elemente, Attribute, Text,... Funktionen zur Navigation im Baum: getnodetype, getnodename getparentnode, getchildnodes, getfirstchild, getnextsibling, getattributes, getelementsbytagname appendchild, removechild gettagname, {get,set}attributenode höherer Speicherverbrauch
das Beispiel als Baum book library ATTRIBUTE title author author book ATTRIBUTE... TEXT TEXT TEXT
XML::DOM verwendet XML::Parser Knoten: XML::DOM::Node Unterklassen: XML::DOM::Element, XML::DOM::Text weitere Klassen: XML::DOM::Comment, XML::DOM::Entity, XML::DOM::NodeList,...
XML::DOM, cont. use XML::DOM; my $parser = XML::DOM::Parser->new; my $root = $parser->parsefile( intro.xml ); walktree($root); print $root->tostring; sub walktree { my ($node) = @_; $node->settagname( strong ) if $node->getnodename eq blink ; walktree($_) foreach $node->getchildnodes; }
XML::DOM, cont. Zugriff auf einzelne Elemente kompliziert: foreach $book ($root->getelementsbytagname( book )) { my $title = $book->getelementsbytagname( title ) ->item(0)->getfirstchild->getdata; my $attrs = $book->getattributes; my $year = $attrs->getnameditem( year )->getvalue; my $ed = $attrs->getnameditem( edition )->getvalue if $attrs->getnameditem( edition );... } mixed content schwierig
XPath Anfrage-Sprache beschreibt Pfade im XML-Dokument andere Baumstruktur als DOM Syntax an (Unix-)Dateisystem angelehnt einfacher Zugriff auf Inhalte von Elementen und Attribute Achsen: child, parent, sibling, attribute,... Bedingungen
XPath, cont. Beispiele: author alle author-kinder des aktuellen Knotens book/title title-element unterhalb von book /library library-element unterhalb der Wurzel //title alle title-elemente im Dokument book/@year year-attribut //book[@year= 2000 ] alle Bücher aus dem Jahr 2000 //author[position()=1] erste author-elemente //book[@year= 2000 ]/title Titel aller Bücher aus 2000
XML::XPath use XML::XPath; my $root = XML::XPath->new(filename => library.xml ); my $books = $root->find( /library/book[@year=2000] ); foreach $book ($books->get_nodelist) { my $title = $book->findvalue( title ); my $authors = $book->find( author ); my $author = join(", ", map {$_->findvalue(. )} $authors->get_nodelist); my $year = $book->findvalue( @year ); my $edition = $book->findvalue( @edition );... }
XML mit Perl erzeugen erneut: print, here-documents Schwierigkeit: keine vorgegebenen Tags, Attribute, Entitäten zwei Module: XML::Writer, XML::Generator bisher kein Äquivalent zu HTML::Element->new_from_lol Serialisierung von Datenstrukturen
XML::Writer use XML::Writer; my $writer = XML::Writer->new( DATA_MODE => 1, DATA_INDENT => 2); $writer->xmldecl; $writer->starttag( library ); $writer->starttag( book, year => 2000, edition => "3"); $writer->dataelement( title, "Programming Perl"); $writer->dataelement( author, "Larry Wall"); $writer->dataelement( author, "Tom Christiansen"); $writer->dataelement( author, "Jon Orwant"); $writer->endtag( book ); $writer->endtag( library ); $writer->end;
XML::Generator use XML::Generator; my $xml = XML::Generator->new( pretty => 2, conformance => strict ); print $xml->library( $xml->book({edition => 3, year => 2000}, $xml->title( Programming Perl ), $xml->author( Larry Wall ), $xml->author( Tom Christiansen ), $xml->author( Jon Orwant )), $xml->book({year => 1998}, $xml->title( Advanced Perl Programming ), $xml->author( Sriram Srinivasan )));
XML::Dumper use XML::Dumper; %bands = (beatles => { members => [ John, Paul, George, Ringo ], albums => [ Help, Revolver ]}, thewho => { members => [ Roger, Pete, John, Keith ], albums => [ Quadrophenia ] }); my $dumper = XML::Dumper->new; print $dumper->pl2xml(\%bands);
XML::Dumper, cont. <perldata> <hash> <item key="beatles"> <hash> <item key="albums"> <array> <item key="0">help</item> <item key="1">revolver</item> </array> </item> <item key="members"> <array> <item key="0">john</item> <item key="1">paul</item> <item key="2">george</item> <item key="3">ringo</item> </array> </item> </hash> </item>... </perldata>