提取变量并将其添加到单独的XML文件

时间:2016-12-08 19:54:09

标签: xml perl

我有一个登录并返回会话ID的脚本。我需要会话ID,以便我可以填充XML文件来处理它,例如为托儿所创建一个工厂房间。

#!/usr/bin/perl -w

use strict;

use LWP::UserAgent;
use Data::Dumper;
use XML::Simple;

my $authenticate = do {
    open my $fh, '<', '/tmp/login.xml' or die "Could not open file: $!";
    local $/;
    <$fh>;
};

my $webpage = "https://www.example.com/api";

my $ua = LWP::UserAgent->new;
my $response = $ua->post($webpage, Content_Type => 'text/xml',
                                        Content => $authenticate);


if ( $response->is_success) {

    my $xml = new XML::Simple;
    my $x = $response->decoded_content;

    # read XML file
    my $data = $xml->XMLin($x);

    my $sessionid =  $data->{'sessionid'};

...

我需要获取该sessionid变量并插入另一个看起来像这样的xml文件:

<xml>
  <API>4.0</API>
  <action>plant_room_add</action>
  <enforce_rules_training>0</enforce_rules_training>
  <id>3</id>
  <location>123456</location>
  <name>Test1</name>
  <sessionid>$sessionid</sessionid>
  <signature>Hello World</signature>
  <terminal_id>xxxxxxx</terminal_id>
  <training>1</training>
</xml>

我知道我可以将plant_root_add XML放在同一个脚本中,但我认为这个脚本会随着时间的推移而增长,所以我可能需要一个脚本来删除工厂房间。这用于监控,每60秒执行一次。

这样做的方法是什么?

1 个答案:

答案 0 :(得分:4)

请勿使用XML::Simple。至少可以说,XML::LibXMLXML::Twig都要好得多。

我无法展示如何从第一个XML中提取数据(因为它未显示),但以下是使用XML::LibXML编辑其他XML文件的方法。我建议用这个模块重写第一个操作。

通过XPath表达式查找节点并替换元素的文本节点子节点:删除并添加。

use warnings;
use strict;    
use XML::LibXML;

# ... your code that establishes the $session_id variable ...
my $session_id = 'SAMPLE_ID';
my $filename = 'another.xml';

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

my ($node) = $doc->findnodes('//sessionid');
$node->removeChildNodes();
$node->appendText($session_id);    

# print $doc->toString;
$doc->toFile('edited_' . $filename);  # or just $filename to overwrite

XML::LibXML与此最相关的文档适用于TextElementNode类。另请参阅ParserDocument的页面。以下是XPath specificationtutorial (w3schools)

一些评论。

我们可以先创建解析器对象

,而不是直接加载文件
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($filename);

使用解析器,我们可以在构造函数之外使用its configuration的方法(在解析之前仍然是静态的),这提供了更多的灵活性。

根据您的目的,还有其他方法可以更改数据。例如

$node->firstChild->setData($session_id);

更具体。它使用XML::LibXML::Node

中的firstChild
  

如果某个节点有子节点,则此函数将返回子列表中的第一个节点。

来自XML::LibXML::Text

setData

  

此函数将文本内容设置或替换为节点。该节点必须是&#34; text&#34;,&#34; cdata&#34;或&#34;评论&#34;。

这适用于那个孩子,&#34; 子列表中的第一个节点。&#34;

如果元素有子元素,我们也可以通过findnodes('//sessionid/text()')获取文本节点并直接使用setData(在该子元素上)。你可能想要在答案中这样做。