Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
474 views
in Technique[技术] by (71.8m points)

perl - Extract a variable and add it to a separate XML file

I have a script that logs in and returns a session ID. I need the session ID so that I can populate an XML file to do stuff with it, for example create a plant room for a nursery.

#!/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'};

...

I need to take that sessionid variable and insert into another xml file that looks like this:

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

I know that I can put the plant_root_add XML in the same script, but I think this script is growing to grow over time so I might need a script to delete the plant room. This is for monitoring and it will be executed every 60 seconds.

What is the way to do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Do not use XML::Simple. Both XML::LibXML and XML::Twig are far better, to say the least.

I can't show how to pull data from the first XML since it's not shown, but here is how to edit that other XML file using XML::LibXML. I suggest to rewrite the first operation with this module as well.

Find the node via an XPath expression and replace element's text-node children: remove and add.

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

Documentation on XML::LibXML most relevant to this is for Text, Element, and Node classes. See also pages for Parser and Document. Here is XPath specification and a tutorial (w3schools).


A few comments.

Instead of loading the file directly we can create the parser object first

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($filename);

With the parser on hand we can use methods for its configuration outside of the constructor (while stilll before parsing), what provides more flexibility.

There are other ways to change data, depending on your purpose. For example

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

is more specific. It uses firstChild from XML::LibXML::Node

If a node has child nodes this function will return the first node in the child list.

and setData from XML::LibXML::Text

This function sets or replaces text content to a node. The node has to be of the type "text", "cdata" or "comment".

This works for that one child, "the first node in the child list."

We can also get the text node by findnodes('//sessionid/text()') and use setData (on that one child) directly, if the element has children. You probably want to do as in the answer though.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...