2016-04-29 6 views
1

Ich möchte Attribute in XML mit Perl aktualisieren. Das Problem hier ist, wenn ich die Attribute von XML aktualisiert, es passiert, aber das XML-Format wird geändert.Breaking mein Kopf, aber nutzlos!Perl-Code zum Aktualisieren von Attributen in xml ohne Auswirkungen auf das XML-Format

Kann pls jemand mir einige Perl-Code vorschlagen Attribute in XML zu bearbeiten, um die Perl-Code das XML-Format

I beeinflussen verwendet, wie unten

#!/usr/bin/perl 
use strict; 
use warnings; 
use XML::Simple; 

my $xml_file = '3.xml'; 

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

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

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

Eingang xml gezeigt:

<outer1> 
    <inner1> 
    <name>Stonecold</name> 
    <org>wwf</org> 
    <profession> 
     <Bowler>hai</Bowler> 
    </profession> 
    </inner1> 
    <inner1> 
    <name first = "Shanebond" /> 
    <org>newzealand</org> 
    <profession>Shane Bond</profession> 
    </inner1> 
    <inner1> 
    <name>brain schemidit</name> 
    <org>Google</org> 
    <profession>Chairman</profession> 
    </inner1> 
</outer1> 

Erwartete Ausgabe xml:

<outer1> 
    <inner1> 
    <name>Stonecold</name> 
    <org>wwf</org> 
    <profession> 
     <Bowler>hai</Bowler> 
    </profession> 
    </inner1> 
    <inner1> 
    <name first = "Shane Bond" /> 
    <org>newzealand</org> 
    <profession>Shane Bond</profession> 
    </inner1> 
    <inner1> 
    <name>brain schemidit</name> 
    <org>Google</org> 
    <profession>Chairman</profession> 
    </inner1> 
</outer1> 

Tatsächliche Ausgabe xml:

<outer1> 
    <inner1> 
    <name>Stonecold</name> 
    <org>wwf</org> 
    <profession> 
    <Bowler>hai</Bowler> 
    </profession> 
    </inner1> 
    <inner1> 
    <name> 
     <first>Shane Bond</first> 
    </name> 
    <org>newzealand</org> 
    <profession>Shane Bond</profession> 
    </inner1> 
    <inner1> 
    <name>brain schemidit</name> 
    <org>Google</org> 
    <profession>Chairman</profession> 
    </inner1> 
</outer1> 
+0

[? * Warum XML :: Simple "Entmutigt" *] (http://stackoverflow.com/questions/33267765/why-is-xmlsimple-discouraged) – Borodin

Antwort

0

Es gibt viele Möglichkeiten, diese Katze zu häuten. Eine ist XML::LibXML zu verwenden. Ihr Beispiel würde so aussehen;

use v5.12; 
use warnings; 
use XML::LibXML; 

my $filename = '3.xml' ; 
my $xpath = '//name[contains(@first, "Shane")]' ; 

my $dom = XML::LibXML->load_xml(
    location => $filename 
); 

for my $td ($dom->findnodes($xpath)) { 
    $td->setAttribute("first" , "Shane Bond"); 
} 

say $dom->toString();  # print the updated XML 
$dom->toFile("3.xml.new"); # alterntaively, dump it to a file 

wenn es auf der Datei oben lief, produziert es;

<?xml version="1.0"?> 
<outer1> 
    <inner1> 
    <name>Stonecold</name> 
    <org>wwf</org> 
    <profession> 
     <Bowler>hai</Bowler> 
    </profession> 
    </inner1> 
    <inner1> 
    <name first="Shane Bond"/> 
    <org>newzealand</org> 
    <profession>Shane Bond</profession> 
    </inner1> 
    <inner1> 
    <name>brain schemidit</name> 
    <org>Google</org> 
    <profession>Chairman</profession> 
    </inner1> 
</outer1> 

XPath ist eine Abfragesprache - in diesem Fall die $xpath Variable ist eine Anforderung für alle Knoten im Dokument mit dem Namen name und ein Attribut first genannt, die die Zeichenfolge Shane enthält. Ein alternativer Weg, dies zu tun, besteht darin, $xpath auf einfach //name zu setzen und die zweite Iteration durch die Schleife würde den korrekten Knoten haben.

Es gibt eine ausgezeichnete "Tutorial Beispiel vorangehen" auf XML::LibXML von Grant McLeanhere. Ein wenig Lesen dort sollte ähnliche Probleme lösen.

+0

Hi Marty, vielen Dank für die Freigabe des obigen Codes, ich kann die erwartete Ausgabe auf der Konsole sehen, aber die XML-Datei wird nicht aktualisiert, was benötigt wird. Kannst du irgendwas für die Xml-Datei-Aktualisierung vorschlagen. – kmmmf

+0

Hallo Marty, es funktioniert ..........! Xml-Datei-Update funktioniert gut und Entschuldigung für die späte Antwort – kmmmf

-1

Statt mit XML :: Simple, lesen Sie den Inhalt Zeile für Zeile und führen Sie die Mustererkennung in dem Sie den Attributwert ändern müssen. Dies wird Ihr XML-Inhaltsformat nicht ändern.

Sie können diese Lösung für temporäre Zwecke verwenden.

Aber das ist kein richtiger Weg zu tun. Weil das XML mit Hilfe von XPATH-Wert und mit Mustervergleichswert geändert werden muss.

1

Sie setzen NoAttr => 1 für XMLout(). Die XML::Simple documentation sagt:

NoAttr => 1 # in + out - praktisch

Wenn mit XMLout() verwendet, die erzeugte XML keine Attribute enthält. Alle Hash-Schlüssel/Werte werden stattdessen als verschachtelte Elemente dargestellt.

Bei Verwendung mit XMLin() werden alle Attribute im XML ignoriert.

Sie wollen ein Attribut, aber Attribute ausschalten?

I versucht: Druck XMLout ( XMLin ("t.xml", KeepRoot => 1, ForceArray => 1), KeepRoot => 1 );

Die diff beiden Dateien sehen ok:

$ diff -bBEup t.xml t2.xml 
--- t.xml 2016-04-29 10:36:28.446578760 +0200 
+++ t2.xml 2016-04-29 10:39:03.450073658 +0200 
@@ -7,7 +7,7 @@ 
    </profession> 
    </inner1> 
    <inner1> 
-  <name first = "Shanebond" /> 
+ <name first="Shanebond" /> 
     <org>newzealand</org> 
     <profession>Shane Bond</profession> 
    </inner1> 

Alles sieht ok ohne NoAttr:

$x = XMLin("t.xml", KeepRoot => 1, ForceArray => 1); 
$x->{outer1}->[0]->{inner1}->[1]->{name}->[0]->{first} = "Larry"; 
print XMLout($x, KeepRoot => 1); 

<outer1> 
    <inner1> 
    <name>Stonecold</name> 
    <org>wwf</org> 
    <profession> 
     <Bowler>hai</Bowler> 
    </profession> 
    </inner1> 
    <inner1> 
    <name first="Larry" /> 
    <org>newzealand</org> 
    <profession>Shane Bond</profession> 
    </inner1> 
    <inner1> 
    <name>brain schemidit</name> 
    <org>Google</org> 
    <profession>Chairman</profession> 
    </inner1> 
</outer1> 
+1

Hallo Sebastian, seine Arbeit danke sehr viel ..... – kmmmf

0

Why is XML::Simple "Discouraged"?

Dies ist einer der Gründe, XML::Simple eine schlechte Wahl ist.

So etwas wie XML::Twig kann es wie folgt tun:

#!/usr/bin/perl 
use strict; 
use warnings; 
use XML::Twig; 

my $twig = XML::Twig -> new (pretty_print => 'indented_a'); 
$twig -> parse (\*DATA); 
$twig -> findnodes ('//inner1/name', 1) -> set_att('first', "Shane Bond"); 
$twig -> print; 

__DATA__ 
<outer1> 
    <inner1> 
    <name>Stonecold</name> 
    <org>wwf</org> 
    <profession> 
     <Bowler>hai</Bowler> 
    </profession> 
    </inner1> 
    <inner1> 
    <name first = "Shanebond" /> 
    <org>newzealand</org> 
    <profession>Shane Bond</profession> 
    </inner1> 
    <inner1> 
    <name>brain schemidit</name> 
    <org>Google</org> 
    <profession>Chairman</profession> 
    </inner1> 
</outer1> 

Aber eigentlich würde ich das eher als ‚Ordnung‘ den Knoten vorschlagen, können Sie einfach XPATH verwenden die, die Sie finden wollen:

$twig -> findnodes ('//inner1/name[@first="Shanebond"]', 0) -> set_att('first', "Shane Bond"); 

Dies - anstatt nur das 'zweite' Element auszuwählen, findet das, wo das first Attribut falsch ist und behebt es.

Code So machen:

#!/usr/bin/perl 
use strict; 
use warnings; 
use XML::Twig; 

my $twig = XML::Twig -> new (pretty_print => 'indented_a'); 
$twig -> parsefile ('3.xml') 
$twig -> findnodes ('//inner1/name[@first="Shanebond"]', 0) -> set_att('first', "Shane Bond"); 

open (my $output, '>', '3.new.xml') or die $!; 
print {$output} $twig -> sprint; 
close ($output); 
Verwandte Themen