我正在研究一个需要根据用户输入填充XML文件的Perl脚本。用户将提供国家名称和城市名称。如果他/她提供:japan和e,我需要在日本标签中填充 - 但作为最后一个条目。我怎样才能做到最好?国家标签中的城市可以很多。如何在相应的国家/地区标记中添加城市作为最后一个标记?
每次需要添加城市时,如何在相关国家/地区标记的末尾显示?
PS:我没有使用任何内置数据结构来存储数据。我只是在文件中添加哑行。
Samlple输出XML文件:
<country name="japan-">
<city>a</city>
<city>b</city>
<city>c</city>
<city>d</city>
</country>
<country name="china-">
<city>aa</city>
<city>bb</city>
<city>cc</city>
<city>dd</city>
</country>
我有一个更具体的问题, Change an XML file content via Perl script 。
答案 0 :(得分:4)
XML::Simple是......简单。 :) 它确实需要一个根元素:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
my $xml = join "\n", <DATA>;
my $doc = XMLin($xml, KeepRoot => 1);
# Get the list of cities as a list, then push "Tokyo" to it.
push @{$doc->{countries}->{country}->{'japan-'}->{city}}, 'Tokyo';
print XMLout($doc, KeepRoot => 1);
__DATA__
<countries>
<country name="japan-">
<city>a</city>
<city>b</city>
<city>c</city>
<city>d</city>
</country>
<country name="china-">
<city>aa</city>
<city>bb</city>
<city>cc</city>
<city>dd</city>
</country>
</countries>
输出:
<countries>
<country name="china-">
<city>aa</city>
<city>bb</city>
<city>cc</city>
<city>dd</city>
</country>
<country name="japan-">
<city>a</city>
<city>b</city>
<city>c</city>
<city>d</city>
<city>Tokyo</city>
</country>
</countries>
答案 1 :(得分:0)
我认为您的意思是:如何根据用户输入加载XML文件并添加条目?
如果我明白这一点:你使用像XML :: Simple这样的解析器/编写器(显然更好的是像XML :: Twig,所以请稍微探讨一下)将文件加载到哈希的Perl数据结构中阵列。 (使用Data :: Dumper检查它在内存中的外观。)然后使用正常的Perl数据交互编辑该结构,完成后使用writer将其转换回XML。
答案 2 :(得分:0)
以下是使用XML::Twig的解决方案。我认为它做你想要的。它使用的XML :: Twig最显着的特性是使用id => name
选项将name属性视为ID,因此可以使用$t->elt_id
和insert_new_elt
方法直接找到元素在树中创建一个新元素。它的签名是(<position: before, after, first_child or last_child>, <tag_name>, <{attributes}>, <content>
),
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $t= XML::Twig->new( id => 'name', # treat the name attribute as an ID
pretty_print => 'indented'
)
->parse( \*DATA);
add_city( $t, japan => "Kobe");
add_city( $t, japan => "Tokyo");
add_city( $t, china => "Beijing");
add_city( $t, china => "Shanghai");
add_city( $t, japan => "Kobe");
add_city( $t, south_korea => "Seoul");
$t->print;
sub add_city
{ my( $t, $country_name, $city_name)= @_;
my $country= $t->elt_id( $country_name);
if( ! $country)
{ warn "creating country '$country_name'\n";
$country= $t->root->insert_new_elt( last_child => country
=> { name => $country_name }
);
}
if( $country->first_child( qq{city[text()="$city_name"]}))
{ warn "city '$city_name' already found in '$country_name', skipping\n";
return;
}
warn "adding '$city_name' to '$country_name', skipping\n";
$country->insert_new_elt( last_child => 'city', $city_name);
}
__DATA__
<countries>
<country name="japan">
</country>
<country name="china">
</country>
</countries>