2

I have simple XML like this.

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<TCXML format="low_level" authKey="12345">

  <Dataset acl_bits="0" creation_date="2019-04-03T13:42:47Z" dataset_type="#id6" island_id="4" elemId="id2478" last_mod_date="2019-04-03T13:49:31Z" />
  <Dataset acl_bits="0" creation_date="2019-04-03T13:42:47Z" dataset_type="#id61" island_id="41" elemId="id2479" format_used="ASCII" last_mod_date="2019-04-03T13:49:31Z" />

</TCXML>

I am using Perl to change the last_mod_date and resave the xml file.

When I try this Perl code I get the following error.

use strict;
use warnings;
use Data::Dump qw(dump);
use XML::LibXML;
use XML::LibXML::NodeList;
use XML::Simple;
use Data::Dumper;

print "Perl Starting ... \n\n"; 

open my $xmlfilename, '<', 'test100.xml' or die "No input Filename Found ... \n";


my $dom = XML::LibXML->load_xml(IO => $xmlfilename);

print "Looping Dataset ... \n\n"; 
foreach my $xmlNode ($dom->findnodes('//Dataset')) 
{
    my $last_mod_date = $xmlNode->find('./@last_mod_date');

    print "last_mod_date: $last_mod_date ... \n";

    #change dates
    $last_mod_date->setData("2019-04-11");

    #save xml file - can this be done at the very end?
    $dom->toFile('test100.xml');
}

print "\nPerl End ... \n\n"; 

output:

Perl Starting ...

Looping Dataset ...

last_mod_date: 2019-04-03T13:49:31Z ...
Can't locate object method "setData" via package "XML::LibXML::NodeList" at test100.pl line 26.

I have searched Stack Overflow and Google. I carefully read this post but I am still stuck. What am I doing wrong?

halfer
  • 19,824
  • 17
  • 99
  • 186
Sam B
  • 27,273
  • 15
  • 84
  • 121
  • That's because `SetData` is from `XML::LibXML::Text` and works only on particular types of nodes; See [this post](https://stackoverflow.com/a/41051651/4653379) and [this post](https://stackoverflow.com/a/40325142/4653379) for example of `SetData` usage. – zdim Apr 14 '19 at 01:54

1 Answers1

3

For anyone who run's into this in future this is how I got it working. Trick was setValue

foreach my $xmlNode ($dom->findnodes('//Dataset')) 
{
    my ($last_mod_date) = $xmlNode->findnodes('./@last_mod_date');

    print "last_mod_date: $last_mod_date ... \n";

    #change dates
    $last_mod_date->setValue('2019-04-11');

}


    #save xml file at the very end
    $dom->toFile('test100.xml');
Sam B
  • 27,273
  • 15
  • 84
  • 121
  • Or you can use `SetData` on `Text`-type nodes. See [this post](https://stackoverflow.com/a/41051651/4653379) and [this post](https://stackoverflow.com/a/40325142/4653379) – zdim Apr 14 '19 at 01:58
  • @zdim thank you for the links. I will check them out – Sam B Apr 14 '19 at 02:08
  • 1
    Re "*Trick was setValue*", No, the actual fix to the error in the OP was using `my ($last_mod_date)` instead of `my $last_mod_date` to call `find`/`findnodes` in list context. In list context, these returned the individial nodes. In scalar context, they return a ::NodeList object instead. Using `setValue` (a method of ::Attr objects) instead of `setData` (which isn't) fixes a second, different problem. – ikegami Apr 14 '19 at 02:44