Bitte verwenden Sie kein zeilen- und regexbasiertes Parsing von XML. Das ist eine schlechte Idee. Sie können semantisch identisches XML mit unterschiedlicher Formatierung haben, und Regex und zeilenbasiertes Parsing kommen damit einfach nicht zurecht.
Dinge wie unäre Tags und variabler Zeilenumbruch - diese Schnipsel "sagen" das Gleiche:
<root>
<sometag val1="fish" val2="carrot" val3="narf"></sometag>
</root>
<root>
<sometag
val1="fish"
val2="carrot"
val3="narf"></sometag>
</root>
<root
><sometag
val1="fish"
val2="carrot"
val3="narf"
></sometag></root>
<root><sometag val1="fish" val2="carrot" val3="narf"/></root>
Damit ist hoffentlich klar, warum es schwierig ist, einen Regex/Zeilen-basierten Parser zu erstellen? Glücklicherweise müssen Sie das nicht. Viele Skriptsprachen haben mindestens eine, manchmal auch mehrere Parser-Optionen.
Wie ein Vorposter bereits angedeutet hat - xml_grep
ist verfügbar. Das ist eigentlich ein Tool, das auf dem XML::Twig
Perl-Bibliothek. Sie verwendet jedoch "xpath-Ausdrücke", um etwas zu finden, und unterscheidet zwischen Dokumentstruktur, Attributen und "Inhalt".
Z.B.:
xml_grep 'job' jobs.xml --text_only
Im Interesse besserer Antworten finden Sie hier jedoch einige Beispiele für die Erstellung eigener Antworten auf der Grundlage Ihrer Quelldaten:
Erster Weg:
Utilice twig handlers
die Elemente eines bestimmten Typs auffängt und auf sie einwirkt. Der Vorteil dieser Vorgehensweise ist, dass das XML "während der Bearbeitung" geparst wird und Sie es bei Bedarf während der Bearbeitung ändern können. Dies ist besonders nützlich, um "verarbeitetes" XML zu verwerfen, wenn Sie mit großen Dateien arbeiten, indem Sie purge
o flush
:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
XML::Twig->new(
twig_handlers => {
'job' => sub { print $_ ->text }
}
)->parse( <> );
Das wird die <>
um Eingaben entgegenzunehmen (über die Pipeline oder über die Befehlszeile angegeben) ./myscript somefile.xml
) und verarbeiten sie - jede job
Element, wird der zugehörige Text extrahiert und gedruckt. (Sie möchten vielleicht print $_ -> text,"\n"
um einen Zeilenvorschub einzufügen).
Da es auf "Job"-Elemente abgestimmt ist, wird es auch auf verschachtelte Job-Elemente abgestimmt:
<job>programming
<job>anotherjob</job>
</job>
wird zweimal übereinstimmen, aber auch einen Teil der Ausgabe zweimal ausgeben. Sie können jedoch eine Übereinstimmung mit /job
wenn Sie dies bevorzugen. Nützlich - damit können Sie z. B. ein Element drucken und löschen oder ein Element kopieren und einfügen und dabei die XML-Struktur ändern.
Alternativ - zuerst parsen und dann anhand der Struktur "drucken":
my $twig = XML::Twig->new( )->parse( <> );
print $twig -> root -> text;
Als job
Ihr Root-Element ist, brauchen wir nur den Text zu drucken.
Aber wir können ein bisschen anspruchsvoller sein und auf Folgendes achten job
o /job
und drucken Sie stattdessen genau das:
my $twig = XML::Twig->new( )->parse( <> );
print $twig -> findnodes('/job',0)->text;
Sie können verwenden XML::Twig
s pretty_print
um auch Ihre XML-Datei neu zu formatieren:
XML::Twig->new( 'pretty_print' => 'indented_a' )->parse( <> ) -> print;
Es gibt eine Vielzahl von Ausgabeformaten, aber für einfachere XML-Dateien (wie Ihre) sehen die meisten ziemlich ähnlich aus.
0 Stimmen
Wenn Ihre XML-Datei dies enthalten würde: <?xml version="1.0" encoding="utf-8"?> <job xmlns=" sample.com/">Tom & Jerry</job> würden Sie wollen, dass das Ergebnis XML-Escaping in Ruhe gelassen wird: Tom & Jerry oder möchten Sie, dass das Escaping rückgängig gemacht wird, wie es ein XML-Parser tun würde: Tom & Jerry Wenn letzteres der Fall ist, weiß ich leider nicht, wie man das mit Unix-Textprogrammen macht.
0 Stimmen
@Paul
s/&/\&/g
, auch für"
usw., natürlich wird es nicht für benutzerdefinierte Entitäten usw. verallgemeinert.0 Stimmen
https://stackoverflow.com/a/17333829/3291390