2009-08-25 9 views
5

Ich habe eine XML-Datei des Formats:In Perl, wie kann ich ein Element in einer XML-Datei ändern, ohne das Format der XML-Datei zu ändern?

<outer1> 
    <inner1> 
     <name>Stonecold</name> 
     <profession>warrior</profession> 
     <org>wwf</org> 
    </inner1> 
    <inner1> 
     <name>Shanebond</name> 
     <profession>Bowler</profession> 
     <org>newzealand</org> 
    </inner1> 
    <inner1> 
     <name>brain schemidit</name> 
     <profession>Chairman</profession> 
     <org>Google</org> 
    </inner1> 
</outer1> 

Ich möchte den Wert von Shanebond zu Shane Bond ändern.

Ich war mit XML::Simple, aber das Ergebnis war ein Hash.

Ich möchte das gleiche Format wie die Eingabedatei. ZB: Die Ausgabedatei sollte wie folgt aussehen:

<outer1> 
    <inner1> 
     <name>Stonecold</name> 
     <profession>warrior</profession> 
     <org>wwf</org> 
    </inner1> 
    <inner1> 
     <name>Shane Bond</name> 
     <profession>Bowler</profession> 
     <org>newzealand</org> 
    </inner1> 
    <inner1> 
     <name>brain schemidit</name> 
     <profession>Chairman</profession> 
     <org>Google</org> 
    </inner1> 
</outer1> 

Bitte beraten Sie, wie Sie dies tun.

Vielen Dank im Voraus.

Ich mag, dass die Ausgabedatei im selben Verzeichnis und wenn möglich mit dem gleichen Namen gespeichert werden. ist es möglich?

+1

Was ist falsch an einem Hash? – innaM

+0

Die XML-Datei ist eine Konfigurationsdatei und die Komponente, die sie verwendet, kann die Hash-Datei nicht lesen. Auch wenn das Format nach dem Erstellen der Datei geändert wird, kann auch die Komponente den Wert aus der Konfigurationsdatei nicht lesen. –

+1

XMLin -> Prozessinhalt -> XMLout – innaM

Antwort

4

XML::Simple Optionen, die Sie festlegen können, wie Eingang wird in eine Perl-Datenstruktur transformiert werden und wie diese Struktur wird ausgegeben:

#!/usr/bin/perl 

use strict; 
use warnings; 

use XML::Simple; 

my $xml_file = 'b.xml'; 

my $xml = XMLin(
    $xml_file, 
    KeepRoot => 1, 
    ForceArray => 1, 
); 

$xml->{outer1}->[0]->{inner1}->[1]->{name} = 'Shane Bond'; 

XMLout(
    $xml, 
    KeepRoot => 1, 
    NoAttr => 1, 
    OutputFile => $xml_file, 
); 

XML::Simple ein wenig behaart ist, wenn man alles tun, interessant, weil ihr Zweck nicht als Allzweck-XML-Bibliothek ist aber zu schaffen, eine einfache Art zu handeln mit Konfigurationsdateien in XML geschrieben.

CPAN hat eine Fülle von XML related modules. Wenn es sich nicht um ein einmaliges Problem handelt, mit dem Sie sich befassen müssen, wäre es sinnvoll, sich einige der leistungsfähigeren und besser geeigneten Module anzusehen.

+0

Ich möchte die Ausgabedatei im selben Verzeichnis und wenn möglich mit dem gleichen Namen gespeichert werden. ist es möglich? –

+0

@pchakraborty Natürlich ist es möglich. Nifle hat sogar gezeigt, wie es geht. Die Dokumentation erklärt 'OutputFile' deutlich. Lies sie gelegentlich: Sie helfen. –

+0

Ich habe das versucht und es funktioniert einwandfrei. Ich muss es in den Hauptcode einfügen und dann das Ergebnis überprüfen. danke für Ihre Hilfe. –

3

Haben Sie XMLout with OutputFile versucht

Aus der Dokumentation für XML :: Simple:

Das Standardverhalten von XMLout() ist die XML als String zurück. Wenn Sie das XML in eine Datei schreiben möchten, geben Sie einfach den Dateinamen mit der Option 'OutputFile' ein.
Diese Option akzeptiert auch ein IO-Handle-Objekt - besonders nützlich in Perl 5.8.0 und später für die Ausgabe unter Verwendung einer anderen Codierung als UTF-8, zum Beispiel:

open my $fh, '>:encoding(iso-8859-1)', $path or die "open($path): $!"; 
XMLout($ref, OutputFile => $fh); 
+0

Ich habe dies versucht und es funktioniert ordnungsgemäß. Ich muss es in den Hauptcode einfügen und dann das Ergebnis überprüfen. danke für Ihre Hilfe. –

8

Wenn es um das Lesen kommt oder eine XML-Datei zu manipulieren, dann ist XML::Twig oft das erste Werkzeug, das ich verwenden zu suchen.

Zuerst dachte ich, es vielleicht ein Overkill für Ihre Anforderung aber dann bemerkte ich es mit einem parsefile_inplace() Option kam:

use strict; 
use warnings; 
use XML::Twig; 

XML::Twig->new(
    pretty_print => 'indented', 
    twig_handlers => { 
     name => sub { 
      $_->set_text('Shane Bond')->flush if $_->text eq 'Shanebond' 
     }, 
    }, 
)->parsefile_inplace('data.xml', 'bak_*'); 

NB. Wenn Sie keine Sicherungsdatei behalten möchten, entfernen Sie das zweite Argument ('bak_ *').

4

Warum sollte es überhaupt als XML verarbeitet werden? Warum nicht einfach einen regexp-ersetzen?

perl -pi -e 's/Shanebond/Shane Bond/' filename.xml 

Das wird den Ersatz an Ort und Stelle tun, den gleichen Dateinamen und alles behalten.

Verwandte Themen