2016-04-29 20 views
1

perlを使用してxmlの属性を更新したいと思います。ここでの問題は、XMLの属性を更新しているのにXML形式が変更されているときです。私の頭は使用しない!xmlの属性をxml形式に影響を与えずに更新するperlコード

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

誰PLS

#!/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, 
); 

入力XML以下のように私はPerlコードを使用するXMLフォーマット

に影響を与えるアウトして、XMLの属性を更新するために、私にいくつかのPerlコードをお勧めできます

期待される出力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> 

実際の出力のxml:代わりに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

[?* XML :: Simpleはは "落胆" されたのはなぜ*](http://stackoverflow.com/questions/33267765/why-is-xmlsimple-discouraged) – Borodin

答えて

0

この猫には多くの方法があります。 1つはXML::LibXMLです。あなたの例はこのようになります。

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 

上記のファイルを実行すると、次のようになります。

<?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は、クエリ言語である - この場合には$xpath変数名nameと文字列Shaneが含まれていfirstという属性を持つドキュメント内の任意のノードの要求です。これを行うもう1つの方法は、$xpathを単に//nameに設定し、ループを通る2番目の反復が正しいノードを持つようにすることです。

XML::LibXMLによってグラント・マクリーンhereに優れた「例によるチュートリアル」があります。ちょっとした読書があれば、同様の問題は解決するはずです。

+0

こんにちはMarty、上記のコードを共有してくれてありがとう、私はコンソール上で期待される出力を見ることができますが、xmlファイルは更新されていません。 – kmmmf

+0

こんにちはマーティ、その作業..........! xmlファイルの更新はうまく動いていて、遅い返信のために申し訳ありません – kmmmf

-1

:: Simpleは、ラインによってコンテンツのラインを読んで、あなたは、属性値を変更する必要があるパターンマッチを行います。これにより、XMLコンテンツフォーマットは変更されません。

一時的な目的でこのソリューションを使用できます。

しかし、これは正しい方法ではありません。 XMLはXPATH値とパターン一致値の助けを借りて変更する必要があるためです。

1

XMLout()の場合はNoAttr => 1と設定します。 XML::Simple documentationは言う:

NoAttr => 1#+アウトに - 便利な

XMLout(で使用

)、生成されたXMLに属性が含まれていません。 すべてのハッシュキー/値は、代わりにネストされた要素として表されます。

XMLin()で使用すると、XMLの属性はすべて無視されます。

属性は必要ですが属性をオフにしますか?

私が試み: 印刷XMLoutを( XMLin( "t.xml"、KeepRoot => 1、ForceArray => 1)、 KeepRoot => 1 )。

両方のファイルのdiffが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> 

すべてがNoAttrなしでOKになります。

$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

こんにちはセバスチャン、その作業は非常に感謝..... – kmmmf

0

Why is XML::Simple "Discouraged"?

これはXML::Simpleは悪い選択である理由の一つです。

#!/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> 

をしかし実際に、私はむしろ「発注」のノードよりも、あなたはちょうどあなたが欲しい1を見つけるために、XPathを使用することができますことを示唆していると思います:

XML::Twigのようなものはこのようにそれを行うことができます

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

「second」要素を選択するだけでなく、first属性が正しくない部分を見つけて修正します。

は、だからあなたのコードを作る:

#!/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); 
関連する問題