Verarbeitung von Nicht-XML-Daten

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

Im Filterbeispiel haben wir eine Datei als Eingabe benutzt, die ein XML-Dokument enthielt. Das Beispiel zeigt damit eine der vielen Anwendungsmöglichkeiten von SAX. Eine andere hervorragende Möglichkeit ist das Lesen von Daten aus einem Generator (engl. Driver). Dabei handelt es sich um ein Programm, das einen Strom von SAX-Events aus einer Eingabequelle generiert, die in einem ganz anderen Format vorliegen. Die vom SAX-Generator erzeugten Events können genauso verarbeitet werden, als kämen sie aus einem SAX-Parser. Das ist echt cool, denn wir können einen für XML-Daten entwickelten Prozessor plötzlich für ganz andere Formate benutzen. Der SAX-Eventstrom abstrahiert Daten und Markup, so daß wir uns nicht wirklich darum kümmern müssen. Das Programm dann mit anderen Dateien oder Generatoren arbeiten zu lassen ist relativ einfach.

Um einen Generator in Aktion zu sehen, schreiben wir ein Programm, das das Modul XML::SAXDriver::Excel von Ilya Sterin benutzt, um eine Tabelle von Microsoft Excel in ein XML-Dokument zu konvertieren. Dieses Beispiel zeigt, wie man einen Datenstrom ähnlich einer Pipeline verarbeiten kann, um letzten Endes das gewünschte Format zu erhalten. Ein Objekt vom Typ Spreadsheet::ParseExcel liest die Datei und generiert einen Datenstrom. Ein Objekt vom Typ XML::SAXDriver::Excel übersetzt diesen Datenstrom dann in einen Strom von SAX-Events. Diesen Strom lassen wir von unserem Programm ausgeben.

Zum Testen nehmen wir die folgende Excel-Tabelle:

  A   B
  1   Fußbälle   55
  2    Tennisbälle   33
  3   Pingpongbälle   12
  4   Rauschende Bälle   77

Der SAX-Generator erzeugt für uns neue Elemente und gibt ihnen Namen in der Form der Argumente, die den Handlermethoden entsprechen. Wir geben sie einfach nur aus, wie sie kommen, um uns anzuschauen, wie der Generator das Programm strukturiert. Im Beispiel unten sehen Sie ein einfaches Programm, das genau das leistet.

Beispiel: Programm zum Lesen einer Excel-Tabelle

use XML::SAXDriver::Excel;

# Lies den Namen der zu verarbeitenden Datei
die( "Eine Eingabedatei muß angegeben werden" ) unless( @ARGV );
my $file = shift @ARGV;
print "Datei $file wird gelesen...\n";

# Initialisierung des Parsers
my $handler = new Excel_SAX_Handler;
my %props = ( Source => { SystemId => $file },
Handler => $handler );
my $driver = XML::SAXDriver::Excel->new( %props );

# Start des Parsers
$driver->parse( %props );

# Um SAX-Events zu erhalten, brauchen wir ein Package,
# das die Handlermethoden enthält.
package Excel_SAX_Handler;

# Initialisierung des Objekts    
sub new {
    my $type = shift;
    my $self = {@_};
    return bless( $self, $type );
}

# Erzeuge das Wurzelelement
sub start_document {
    print "<?xml version='1.0' encoding='iso-8859-1'?>\n<doc>\n";
}

# Beende das Wurzelelement
sub end_document {
    print "</doc>\n";
}

# Behandlung von Textdaten
sub characters {
    my( $self, $properties ) = @_;
    my $data = $properties->{'Data'};
    print $data if defined($data);
}

# Start eines neuen Elements, wir geben nur das Start-Tag aus
sub start_element {
    my( $self, $properties ) = @_;
    my $name = $properties->{'Name'};
    print "<$name>";
}

# Ende eines Elements
sub end_element {
    my( $self, $properties ) = @_;
    my $name = $properties->{'Name'};
    print "</$name>";
}

Wie Sie sehen können, ähneln die Handlermethoden denen aus dem vorigen SAX-Beispiel. Nur das, was wir mit den Handlermethoden anfangen, hat sich geändert. Schauen wir uns also an, was aus unserer Testtabelle wird, wenn wir das Programm laufen lassen:

<?xml version='1.0' encoding='ISO-8859-1'?>
<doc>
    <records>
        <record>
            <column1>Fußbälle</column1>
            <column2>55</column2>
        </record>
        <record>
            <column1>Tennisbälle</column1>
            <column2>33</column2>
        </record>
        <record>
            <column1>Pingpongbälle</column1>
            <column2>12</column2>
        </record>
        <record>
            <column1>Rauschende Bälle</column1>
            <column2>77</column2>
        </record>
        <record>
            Use of uninitialized value in print at conv line 39.
            <column1></column1>
            Use of uninitialized value in print at conv line 39.
            <column2></column2>
        </record>
    </records></doc>

Der Generator hat die meiste Arbeit erledigt. Er hat die Elemente erzeugt und die Daten strukturiert. Alles, was wir getan haben, war die Ausgabe der Daten, die er uns über Aufrufe der Handlermethoden gegeben hat. Der Generator verpackt das gesamte Dokument in einem Element <records>, unser eigenes Wurzelelement <doc> war also überflüssig. (In der nächsten Version dieses Beispiels werden wir die Handler start_document( ) und end_document( ) so ändern, daß sie nichts mehr ausgeben.) Jede Zeile der Tabelle ist in einem <record>-Element verpackt. Die je zwei Spalten unterscheiden sich durch die Namen <column1> und <column2>. Alles in allem, gar nicht schlecht für den Anfang.

Sie sehen, wie wir mit einem wirklich minimalen Aufwand unsererseits die gebündelten Kräfte von SAX eingesetzt haben, um ein Datenformat in ein anderes zu konvertieren. Der Generator automatisiert die Konversion praktisch schon, aber er gibt uns dennoch genügend Flexibilität, um die Events unter Kontrolle zu halten. Zum Beispiel können wir fehlerhafte Daten wie die leeren Zeilen eliminieren oder Elemente umbenennen. Auf Wunsch können wir auch komplexere Verarbeitungen durchführen, zum Beispiel Werte addieren oder Zeilen sortieren.

  

  

<< 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