Reputation: 57
I got an XML template which looks like this (excerpt):
<isSomething>_xxx_</isSomething>
<someValue>_xxx_</someValue>
My code is going through the template and replacing the _xxx_ placeholders using XML::LibXML's findnode and setData methods respectively.
In the end it looks like this:
<isSomething>true</isSomething>
<someValue>123.45</someValue>
This does the job, however the recipient system would be more happy if the isSomething tag would look like this in case its true:
<isSomething/>
And would be completely omitted in case it's false. Is there a way to do that with XML::LibXML or should i apply the mighty regex power on the string output?
Upvotes: 1
Views: 269
Reputation: 241858
To remove a node, use removeChild
. To produce an empty element, remove its text child:
#! /usr/bin/perl
use warnings;
use strict;
use XML::LibXML;
my $xml = 'XML::LibXML'->load_xml( string => << '__XML__');
<root>
<node id="a">
<isSomething>_xxx_</isSomething>
<someValue>_xxx_</someValue>
</node>
<node id="b">
<isSomething>_xxx_</isSomething>
<someValue>_xxx_</someValue>
</node>
</root>
__XML__
my %nodes = ( a => [ 'true', 1 ],
b => [ 'false', 2 ],
);
for my $node ($xml->documentElement->findnodes('//node')) {
my $id = $node->{id};
my ($is_something, $value) = @{ $nodes{$id} };
my ($s) = $node->findnodes('isSomething[.="_xxx_"]');
if ('true' eq $is_something) {
my ($text) = $s->findnodes('text()');
$s->removeChild($text);
} else {
$node->removeChild($s);
}
my ($v) = $node->findnodes('someValue/text()[.="_xxx_"]');
$v->setData($value);
}
print $xml;
Upvotes: 5
Reputation: 53478
So first - please don't regex your XML. It's dirty. RegEx match open tags except XHTML self-contained tags
I think what you will be wanting is LibXML::XML::Element
- specifically:
new
$node = XML::LibXML::Element->new( $name );
This function creates a new node unbound to any DOM.
Followed by:
$node->replaceNode($newNode);
Upvotes: 4