Skip Menu |

This queue is for tickets about the XML-Twig CPAN distribution.

Report information
The Basics
Id: 125473
Status: open
Priority: 0/
Queue: XML-Twig

People
Owner: Nobody in particular
Requestors: chrispitude [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 3.52
Fixed in: (no value)



Subject: wrap_children() fails with 'Can't call method "wrap_in" on an undefined value at...'
The wrap_children() method fails with Can't call method "wrap_in" on an undefined value at /usr/share/perl5/XML/Twig.pm line 9312. when I do the following: 1. Read in an original twig. 2. Make a new twig and twig root. 3. Set the contents of the new twig's root to stuff I cut from the original twig. 4. Perform a wrap_children() on the new contents. In the included testcase, somehow the handler that sets an ID on the <about> tag is related to the problem; commenting that handler averts the problem.
Subject: wc_bug.pl
#!/usr/bin/perl use strict; use warnings; use XML::Twig; my $xml = <<EOF; <?xml version="1.0" encoding="UTF-8"?> <manual> <about> <title/> <intro/> </about> </manual> EOF # read in original twig my $origtwig=XML::Twig->new( twig_handlers => { 'about[!@id]' => sub { $_->set_att('id', 'ID123'); return 1; }, }); $origtwig->parse($xml); # make a new twig and move contents over to it my $bookmap = XML::Twig::Elt->new('bookmap'); my $newtwig=XML::Twig->new; $newtwig->set_root($bookmap); $bookmap->set_content($origtwig->root->cut_children); #### broken #### $bookmap->wrap_children('<about>', 'frontmatter'); #### broken #### $newtwig->print(pretty_print => 'indented');
I found a variation to the original bug (I think). I've attached a simplified testcase. The root cause seems to be messing with IDs inside a handler. Maybe it's because I'm changing the parent ID before the parent has closed? I'm not sure.
Subject: wc_bug2.pl
#!/usr/bin/perl use strict; use warnings; use XML::Twig; my $xml = <<EOF; <manual> <partdiv/> <chapter> <number/> <title id="ID1"/> </chapter> </manual> EOF my $twig=XML::Twig->new ( keep_encoding => 1, pi => 'drop', comments => 'keep' ); $twig->setTwigHandlers({ 'title' => sub { my $id = $_->id; $_->set_id('OLD'); $_->parent->set_id($id); return 1; }, }); $twig->parse($xml); $twig->root->first_child('chapter')->wrap_children('.*', 'body'); $twig->root->first_child('chapter')->cut_children('body'); #### broken #### $twig->root->wrap_children('<partdiv><chapter>+', 'part'); #### broken #### $twig->print(pretty_print => 'indented');
Subject: Re: [rt.cpan.org #125473] wrap_children() fails with 'Can't call method "wrap_in" on an undefined value at...'
Date: Thu, 25 Oct 2018 13:16:06 +0200
To: bug-XML-Twig [...] rt.cpan.org
From: mirod <xmltwig [...] gmail.com>
On 25/10/18 00:29, chrispitude@gmail.com via RT wrote: Show quoted text
> Queue: XML-Twig > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=125473 > > > I found a variation to the original bug (I think). I've attached a simplified testcase. The root cause seems to be messing with IDs inside a handler. Maybe it's because I'm changing the parent ID before the parent has closed? I'm not sure. >
Hi, this seems likely, the attributes that can be found in the XML are taken straight from the XML (ie you should not change them from within the handler). IIRC "hidden" attributes (the ones that start with #) can be changed and should be available. I can't check right now though, being on vacation until Tuesday. -- Michel
This one is due to the fact that when you create the new XML::Twig element ($bookmap) and when you move elements to it, the id table is not updated. It might be difficult to do this efficiently in all cases, but in the meantime you can do this manually, by inserting the following line before the wrap_children call: foreach my $elt ($bookmap->descendants( '*[@id]')) { $elt->set_id( $elt->att( 'id')); } This makes sure all elements which have an id are listed in the twig's internal id list. __ mirod
By "this one" I meant the first case. The second one seems to have uncovered a bug in the way id's are handled, I have to investigate some more.