简体   繁体   English

用于填充XML文件的Perl脚本

[英]Perl script to populate an XML file

I am working on a Perl script which needs to populate an XML file based on user input. 我正在研究一个Perl脚本,它需要根据用户输入填充XML文件。 The user would provide a country name and a city name. 用户将提供国家名称和城市名称。 If he/she provides: japan and e, I need to populate that in the japan tag - but as the last entry. 如果他/她提供:japan和e,我需要在日本标签中填充 - 但作为最后一个条目。 How best can I achieve this? 我怎样才能做到最好? The cities in country tag can be many. 国家标签中的城市可以很多。 How can I add a city as a last tag inside corresponding country tag? 如何在相应的国家/地区标记内添加城市作为最后一个标记?

How can I reach at the end of relevant country tag each time I need to add a city? 每次我需要添加城市时,如何在相关国家/地区标记的末尾显示?

PS: I am not using any in-built data structures to store data. PS:我没有使用任何内置数据结构来存储数据。 I am just adding dumb lines in the file. 我只是在文件中添加哑行。

Samlple output XML file: 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>

I've a more concrete question, Change an XML file content via Perl script . 我有一个更具体的问题, 通过Perl脚本更改XML文件内容

XML::Simple is... Simple. XML ::简单就是......简单。 :) It does require a root element though: :)它确实需要一个根元素:

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

Output: 输出:

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

I think you meant: How do I load an XML file and add entries to it based on user input? 我想你的意思是:如何加载XML文件并根据用户输入添加条目?

If I understood that right: You use a parser/writer like XML::Simple (there are apparently better ones like XML::Twig too, so explore a bit) to load the file into a Perl data structure of hashes and arrays. 如果我明白这一点:你使用像XML :: Simple这样的解析器/编写器(显然更好的是像XML :: Twig,所以要探索一下)将文件加载到哈希和数组的Perl数据结构中。 (Use Data::Dumper to check how it looks like in memory.) Then you edit that structure with normal Perl data interaction and when done use the writer to convert it back to XML. (使用Data :: Dumper检查它在内存中的外观。)然后使用正常的Perl数据交互编辑该结构,完成后使用writer将其转换回XML。

Below is a solution using XML::Twig . 下面是使用XML :: Twig的解决方案。 I think it does what you want. 我认为它做你想要的。 The most notable features of XML::Twig it uses are the use of id => name option to treat the name attribute as an ID so elements can be found directly with $t->elt_id , and the insert_new_elt method to creates a new element in the tree. 它使用的XML :: Twig最显着的特性是使用id => name选项将name属性视为ID,因此可以使用$t->elt_id直接找到元素,并使用insert_new_elt方法创建新元素在树上。 Its signature is ( <position: before, after, first_child or last_child>, <tag_name>, <{attributes}>, <content> ), 它的签名是( <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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM