michael99 has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I would like to replace the top id of my xml file. But somehow I did not even success to get it. My code below works for other child nodes but not the id. Need help.

Here is my xml file:

<header> <idset id="100"> <a>item_a</a> <b>item_b</b> </idset> </header>
Here is my code:
#!/usr/bin/perl use strict; use warnings; use feature 'say'; use XML::LibXML; my $file = 'test.xml'; #my $node; my $parser = XML::LibXML->new(); my $doc = $parser->load_xml(location => $file); my($object11) = $doc->findnodes('/header/idset'); say 'a: ',$object11->findvalue('./a'); say 'b: ',$object11->findvalue('./b'); say 'id: ',$object11->findvalue('./id');

Current Result:

a: item_a

b: item_b

id:

Expecting Result:

a: item_a

b: item_b

id: 100

Replies are listed 'Best First'.
Re: Replace xml first id
by choroba (Cardinal) on Apr 22, 2020 at 13:30 UTC
    In a XPath Expression, bare id means "element named id", attributes start with the at-sign (already noted by Corion):
    say 'id: ', $object11->findvalue('@id');

    But with XML::LibXML, you can get to an attribute value by a shortcut: you can pretend the element is a hash reference and ask for a key:

    say 'id: ', $object11->{id};

    In xsh, the whole program can be shortened to

    open test.xml ; cd header/idset ; echo (a) ; echo (b) ; echo @id ;

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Replace xml first id
by marto (Cardinal) on Apr 22, 2020 at 12:23 UTC

    You are trying to alter an attribute:

    #!/usr/bin/perl use strict; use warnings; use feature 'say'; use Mojo::DOM; my $xml = '<header> <idset id="100"> <a>item_a</a> <b>item_b</b> </idset> </header>'; my $dom = Mojo::DOM->new->xml(1)->parse( $xml ); # say current attribute value say 'Current value: ' . $dom->at('idset:first-of-type')->attr('id'); # change it to something $dom->at('idset:first-of-type')->attr(id => 'derp'); # dump the whole DOM say $dom->content;

    Output:

    Current value: 100 <header> <idset id="derp"> <a>item_a</a> <b>item_b</b> </idset> </header>
Re: Replace xml first id
by hippo (Archbishop) on Apr 22, 2020 at 12:35 UTC

    If you want details of an attribute then you need to invoke the appropriate method such as XML::LibXML::Node->attributes.

    #!/usr/bin/env perl use strict; use warnings; use XML::LibXML; my $dom = XML::LibXML->load_xml (string => <<'EOT'); <?xml version="1.0"?> <header> <idset id="100"> <a>item_a</a> <b>item_b</b> </idset> </header> EOT my $object11 = $dom->findnodes ('/header/idset'); my @attrs = $object11->shift->attributes; print "@attrs\n";

    You will see in this example how I have incorporated the XML data into the body of the script which turns it into an SSCCE. That's what you should be doing when posting here (in addition to posting in the right section, of course).

    See also: XML Technologies

Re: Replace xml first id
by Corion (Patriarch) on Apr 22, 2020 at 12:23 UTC

    The XPath expression ./id will try to find an element <id> below the current node.

    What you are looking for is an attribute named id of the current node. The XPath syntax for attributes is @id, but I guess you're better off using the ->getAttribute() method:

    my $id = $object11->getAttribute('id');
Re: Replace xml first id
by marto (Cardinal) on Apr 22, 2020 at 12:14 UTC

    You keep posting questions in the wrong section of the site. A link to Where should I post X? is displayed each time you post.

      Opps, I have never realized that. Thanks for pointing out.