使用从CSV文件读取的数据更新XML文件

时间:2018-01-31 09:59:00

标签: xml perl csv parsing xml-parsing

我正在尝试将值写入XML文件。我有一个CSV输入文件Input.xsv和一个XML模板文件template.xml,我需要使用CSV文件中的名称和IP地址值进行更新。

Input.csv(名称,IP地址)

LAB-1,10.26.0.1
LAB-2,10.26.0.2
LAB-3,10.26.0.3

TEMPLATE.XML

<?xml version="1.0" encoding="UTF-8"?>
<ns0:networkdevice
        xmlns:ns0="network.ers.ise.cisco.com" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:ns1="ers.ise.cisco.com"
        xmlns:ers="ers.ise.cisco.com"
        name="name1">
    <authenticationSettings>
        <enableKeyWrap>true</enableKeyWrap>
        <keyEncryptionKey>1234567890123456</keyEncryptionKey>
        <keyInputFormat>ASCII</keyInputFormat>
        <networkProtocol>RADIUS</networkProtocol>
        <radiusSharedSecret>aaa</radiusSharedSecret>
    </authenticationSettings>
    <coaPort>1700</coaPort>
    <NetworkDeviceIPList>
        <NetworkDeviceIP>
            <ipaddress>1.1.1.1</ipaddress>
            <mask>32</mask>
        </NetworkDeviceIP>
    </NetworkDeviceIPList>
</ns0:networkdevice>

我想从CSV文件中读取名称和IP地址,并将它们写入我的XML模板文件,以便为CSV文件中的每个设备创建HTTP POST请求。

我尝试将值保存在我的XML模板中,但我不确定我是否正确。

#!/usr/bin/perl

use warnings;
use strict;

use Text::CSV;
use XML::TreeBuilder;
use Data::Dumper;

my $xmlbase    = 'template.xml';
my $paramsfile = 'input.csv';

# The list of tags filled from the CSV file
my @taglist = qw( name ipaddress );

my $tree = XML::TreeBuilder->new();
$tree->parsefile($xmlbase);

my $csv = Text::CSV->new();

open my $fh, "<:encoding(utf8)", $paramsfile or die "$paramsfile: $!";

while ( my $row = $csv->getline($fh) ) {

    my $contree = XML::TreeBuilder->new();
    $contree->parsefile($xmlbase);

    my $index = 0;

    for my $tagname ( @taglist ) {        
        my $tag = $contree->look_down('_tag' => $tagname);
        $tag->push_content($row->[$index++]);
    }
}

print '<?xml version="1.0" encoding="UTF-8"?>'."\n";
print $tree->as_XML();

运行脚本后,我收到此错误:

  

无法在此行中找到对象方法“push_content”

此错误引用语句$tag->push_content($row->[$index++]);。我认为这是因为name没有自己的标签。

我在这里有这个元素:

<ns0:networkdevice
        xmlns:ns0="network.ers.ise.cisco.com"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:ns1="ers.ise.cisco.com"
        xmlns:ers="ers.ise.cisco.com"
        name="name1">
标记ns0:networkdevice

中的

当我尝试使用ipaddress时,会打印出来,但是来自template.xml的原始值。它不会从Input.csv获取值,如果它为空,则它保持为空。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

从Perl生成XML的简单方法是使用XML::FromPerl

模板由代码中嵌入的Perl数据结构取代:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use XML::FromPerl qw(xml_from_perl);

my $name = 'LAB-1';
my $ip   = '10.26.0.1';

my $xml = xml_from_perl
  [ 'ns0:networkdevice' => { 'xmlns:ns0' => 'network.ers.ise.cisco.com',
                 'xmlns:xs'  => 'http://www.w3.org/2001/XMLSchema',
                 'xmlns:ns1' => 'ers.ise.cisco.com',
                 'xmlns:ers' => 'ers.ise.cisco.com',
                 name => $name },
    [ authenticationSettings =>
      [ enableKeyWrap => 'true' ],
      [ keyEncryptionKey => '1234567890123456' ],
      [ keyInputFormat => 'ASCII' ],
      [ networkProtocol => 'RADIUS' ],
      [ radiusSharedSecret => 'aaa' ] ],
    [ coaPort => '1700' ],
    [ NetworkDeviceIPList =>
      [ NetworkDeviceIP =>
    [ ipaddress => $ip ],
    [ mask => 32 ] ] ] ];

say $xml->toString(1);

答案 1 :(得分:0)

我对XML::Treebuilder不熟悉,所以会在XML::Twig中给出一个例子。我也会避免使用Text::CSV,因为我认为对于大多数CSV用例来说都是过度杀戮(例如,任何时候你都不担心引用/多行)。

但它会是这样的:

#!/usr/bin/env perl

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

my $xml = XML::Twig -> new -> parsefile ( 'template.xml' );
$xml ->set_pretty_print('indented_a');

open ( my $input, '<', 'input.csv' ) or die $!;

while ( <$input> ) {
   chomp;
   my ( $name, $ip ) = split /,/;
   $xml -> root -> set_att('name', $name );
   $xml -> get_xpath('//ipaddress',0) -> set_text($ip);

   $xml -> print;
}

对于CSV的最后一行,这将生成:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:networkdevice
    name="LAB-3"
    xmlns:ers="ers.ise.cisco.com"
    xmlns:ns0="network.ers.ise.cisco.com"
    xmlns:ns1="ers.ise.cisco.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <authenticationSettings>
    <enableKeyWrap>true</enableKeyWrap>
    <keyEncryptionKey>1234567890123456</keyEncryptionKey>
    <keyInputFormat>ASCII</keyInputFormat>
    <networkProtocol>RADIUS</networkProtocol>
    <radiusSharedSecret>aaa</radiusSharedSecret>
  </authenticationSettings>
  <coaPort>1700</coaPort>
  <NetworkDeviceIPList>
    <NetworkDeviceIP>
      <ipaddress>10.26.0.3</ipaddress>
      <mask>32</mask>
    </NetworkDeviceIP>
  </NetworkDeviceIPList>
</ns0:networkdevice>

看起来像你之后的样子?

如果您想要将其包含在$xml -> sprint或类似内容中,那么您需要POST