1

I'm trying to append a string between <value></value>,

<?xml version="1.0" encoding="UTF-8"?>
<rs:alarm-request throttlesize="100" xmlns:rs="http://url.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.url.com">
    <rs:attribute-filter>
    <search-criteria xmlns="http://www.url">
    <filtered-models>
      <equals>
        <attribute id="0x1144f50">
        <value></value>
        </attribute>
      </equals>
      </filtered-models>
    </search-criteria>
  </rs:attribute-filter>
    <!-- Models of Interest -->
    <rs:target-models>
    </rs:target-models>
</rs:alarm-request>

I used the following code, but I'm keep getting: Can't locate object method "appendTextNode" via package "XML::LibXML::NodeList"

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

# Insert devices MH to GETdevices_xmlbody template
my $doc = $parser->parse_file($current_working_dir.'\GETdevices_xmlbody.xml');
my $elem = $doc->findnodes('//rs:attribute-filter/search-criteria/filtered-models/equals/attribute/value');

# $elem->removeChildNodes();
$elem->appendTextNode('STRING');
1
  • If your XPath would match, then you could use something like $elem->get_node(1)->appendTextNode('STRING'); Commented Sep 27, 2013 at 7:36

2 Answers 2

4

You can use XML::Twig too:

Content of script.pl:

#!/usr/bin/env perl

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

my $twig = XML::Twig->new(
    twig_handlers => {
        '//rs:attribute-filter/search-criteria/filtered-models/equals/attribute/value' => sub {
            $_->set_text('STRING');
        },  
    },  
    pretty_print => 'indented',
)->parsefile( shift )->print;

Run it like:

perl script.pl xmlfile

That yields:

<?xml version="1.0" encoding="UTF-8"?>
<rs:alarm-request throttlesize="100" xmlns:rs="http://url.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.url.com">
  <rs:attribute-filter>
    <search-criteria xmlns="http://www.url">
      <filtered-models>
        <equals>
          <attribute id="0x1144f50">
            <value>STRING</value>
          </attribute>
        </equals>
      </filtered-models>
    </search-criteria>
  </rs:attribute-filter>
  <!-- Models of Interest --> 
  <rs:target-models></rs:target-models>
</rs:alarm-request>
Sign up to request clarification or add additional context in comments.

Comments

3

You asked to get all the nodes matching your criteria. You need to loop over them.

my $elems = $doc->findnodes('...');
for my $elem ($elems->get_nodelist) {
   ...
}

Simpler:

my @elems = $doc->findnodes('...');
for my $elem (@elems) {
   ...
}

If you just expect exactly one, you could just grab the first one.

my ($elem) = $doc->findnodes('...');

1 Comment

This is only one part of the problem. The other is that the XPath does not match at all, because starting from <search-criteria> there's another namespace which has to be dealt with. So either XML::LibXML::XPathContext has to be used, or the XPath expression has to be rewritten to do only /*[local-name()="element"] matches.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.