XML::TreeBuilder

(Auszug aus "Perl & XML" von Erik T. Ray & Jason McIntosh)

XML::TreeBuilder ist eine weitere Klasse zum Aufbau eines Baums von Objekten, die in diesem Fall Instanzen der Klasse XML::Element sind. (Diese Klasse ist abgeleitet von einer älteren Klasse, nämlich HTML::Element. Letztere stammt aus dem HTML::Tree-Paket.) Man kann also einen Baum aus einer Datei mit XML::TreeBuilder lesen und dann die Methoden von XML::Element verwenden, um sich im Baum zu bewegen, Daten zu extrahieren oder den Baum zu modifizieren. Wir konzentrieren uns auf die letztere Möglichkeit: Zugriffsmethoden als Lösung zum Aufbau eines eigenen Baums.

Als Beispiel schreiben wir ein Programm zur Verwaltung einer einfachen Aufgabenliste, die in einer XML-Datei abgespeichert wird. Die Liste ist priorisiert, zu diesem Zweck gibt es Elemente wie »sofort« oder »langfristig«. Falls die Datei leer ist oder fehlt, wird eine leere Liste initialisiert. Der Benutzer kann mit Hilfe der Optionen -s oder -l (für »sofort« oder »langfristig«) Einträge erfassen, wobei er jeweils eine Beschreibung angeben muß. Das Programm schreibt anschließend die geänderte Datei zurück und gibt ihren Inhalt auf den Bildschirm aus.

Den ersten Teil des Programms sehen wir im folgenden Beispiel. Dieser Teil dient dem Aufbau der Baumstruktur. Falls die Datei gefunden wird, wird sie gelesen und zum Aufbau des Baums genutzt. Anderenfalls wird ein leerer Baum erzeugt.

Beispiel: Verwaltung einer Aufgabenliste, erster Teil

use XML::TreeBuilder;
use XML::Element;
use Getopt::Std;

# Kommandozeilenoptionen
# -s sofort
# -l langfristig
#
my %opts;
getopts( 'sl', \%opts );

# Initialisierung des Baums
my $data = 'data.xml';
my $tree;

# Falls die Dateiexistiert, lies sie und baue den Baum daraus auf
if( -r $data ) {
     $tree = XML::TreeBuilder->new( );
     $tree->parse_file($data);     
  
  # Anderenfalls erzeuge einen leeren Baum
} else {
     print "Eine neue Aufgabenliste wird erzeugt.\n";
     my @now = localtime;
     my $date = $now[4] . '/' . $now[3];
     $tree = XML::Element->new( 'aufgabenliste', 'datum' => $date );
     $tree->push_content( XML::Element->new( 'sofort' ));
     $tree->push_content( XML::Element->new( 'langfristig' ));
}

Einige Bemerkungen zur Initialisierung der Struktur sind hier angebracht. Die minimale Baumstruktur einer neuen Datei sieht wie folgt aus:

<aufgabenliste datum="DATUM">
  <sofort></sofort>
  <langfristig></langfristig>
</aufgabenliste>

Die Elemente <sofort> und <langfristig> bilden Ankerpunkte, an denen wir neue Aufgaben eintragen können. Wir brauchen also insgesamt drei Elemente, die wir mit dem Konstruktor von XML::Element, d. h. mit der Methode new( ), erzeugen. Der Elementname ist das erste Argument dieser Methode. Beim ersten Aufruf übergeben wir außerdem ein Argument 'datum' => $date, um ein Attribut namens »datum« zu erzeugen. Die weiteren Knoten müssen mit dem ersten verbunden werden. Zu diesem Zweck wird die Methode push_content( ) aufgerufen, die einen weiteren Knoten an die Kindliste eines Elements anhängt.

Der nächste Teil des Programms ändert den gelesenen oder erzeugten Baum, indem ein vom Benutzer angegebener, neuer Knoten eingefügt wird. Wo dieser Knoten eingefügt wird, hängt von der verwendeten Option (-s oder -l) ab. Abschließend verwenden wir die Methode as_XML, um das Ergebnis wieder in XML umzuwandeln. All das sehen wir im nächsten Beispiel.

Beispiel: Verwaltung einer Aufgabenliste, zweiter Teil

# Eine neue Aufgabe wird eingefügt und das Ergebnis gespeichert
if( %opts ) {      
      my $item = XML::Element->new( 'aufgabe' );
      $item->push_content( shift @ARGV );
      my $place;
      if( $opts{ 's' }) {
            $place = $tree->find_by_tag_name( 'sofort' );
      } elsif( $opts{ 'l' }) {
            $place = $tree->find_by_tag_name( 'langfristig' );
      }
      $place->push_content( $item );
}
open( F, ">$data" ) or die( "Konnte die Aufgabenliste nicht speichern." );
print F "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n", $tree->as_XML;
close F;

Abschließend wollen wir die Aufgabenliste auf den Bildschirm ausgeben. Dabei verwenden wir die Methode find_by_tag_name( ), um vom aufgerufenen Element ausgehend ein Kindelement mit einem vorgegebenen Namen zu finden. Falls mehr als ein solches Element gefunden wird, ist das Ergebnis eine Liste. Zwei weitere Methoden dienen dem Zugriff auf den Inhalt eines Elements: attr_get_i( ) für Attribute und as_text( ) für Textdaten in Elementen. Im Beispiel unten sehen wir den restlichen Quelltext.

Beispiel: Verwaltung einer Aufgabenliste, dritter Teil

# Ausgabe der Aufgabenliste
print "Aufgabenliste für " . $tree->attr_get_i( 'datum' ) . ":\n";
print "\nSofort zu erledigen:\n";
my $sofort = $tree->find_by_tag_name( 'sofort' );
my $count = 1;
foreach my $item ( $sofort->find_by_tag_name( 'aufgabe' )) {
print $count++ . '. ' . $item->as_text . "\n";
}
print "\nIrgendwann:\n";
my $langfristig = $tree->find_by_tag_name( 'langfristig' );
$count = 1;
foreach my $item ( $langfristig->find_by_tag_name( 'aufgabe' )) {
print $count++ . '. ' . $item->as_text . "\n";
}

Um das Programm zu prüfen, haben wir mit einigen Aufrufen die folgende Datei erzeugt. (Die Leerzeichen haben wir von Hand eingefügt, um die Datei lesbarer zu machen.)

<?xml version="1.0" encoding="ISO-8859-1"?>
<aufgabenliste date="7/3">
    <sofort>
        <aufgabe>Den Goldfisch ins Wasser zurückbringen.</aufgabe>
        <aufgabe>Den Blinddarm entfernen lassen.</aufgabe>
    </sofort>
    <langfristig>
        <aufgabe>Den K-2 besteigen.</aufgabe>
        <aufgabe>Anzeichen außerirdischen Lebens finden.</aufgabe>
    </langfristig>
</aufgabenliste>

Auf dem Bildschirm erscheint die folgende Ausgabe:

Aufgabenliste für 7/3:

Sofort zu erledigen:
1.Den Goldfisch ins Wasser zurückbringen.
2.Den Blinddarm entfernen lassen.

Irgendwann:
1. Den K-2 besteigen.
2. Anzeichen außerirdischen Lebens finden.

  

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema Perl & XML bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2003 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Perl & XML" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de