I'm writing a simple Perl script that uses XML::Smart to create and parse an XML file. I have run into a problem with deleting XML nodes. I have the following code:
if ( exists $XML->{object}[$n] ) {
delete $XML->{object}[$n] ;
};
$XML->save('dane.xml') ;
It does what is expected - namely, the correct node is deleted. However, when I later try to list all nodes (children of a particular root), using the code below (which usually works):
my @objects = $XML->{object}('@') ;
foreach my $object (@objects) {
say "$object->{address}";
};
Perl lists all nodes up to the one before the deleted one, and then spits out the following error:
Not a HASH reference at g:/Dwimperl/perl/site/lib/XML/Smart/Tie.pm line 48, <STDIN> line 2.
I'm stumped - I tried using various permutations of $XML->data(); but none worked. I would prefer to continue using XML::Smart for this task, so I hope this problem can be solved within this particular library.
While XML::Smart
is way better than XML::Simple
, on which it is based, in my opinion it is still really not very good at representing XML data. In this case you have to be aware that the node you want to delete is an element of a Perl array, and using delete
on it will simply set the element to undef
while leaving it in place (unless it happens to be the last element of the array).
To manipulate arrays like this you need splice
, which correctly removes elements and moves later ones down to fill the space. Use
splice @{ $XML->{object} }, $n, 1
instead of your delete
and your code should work for you.
Never use exists
and delete
on an array element. Neither do anything useful.
To remove an element from an array, you need to shift down all the other elements. splice
can do this.
splice(@{ $XML->{object} }, $n, 1);
Or if it helps you understand better,
splice(@{ $XML->{object} }, $n, 1, ());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With