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

Hello Monks,

I need to grouping heading and its content. I got output by simple regex find and replace. But I need to do it using XML::Twig.

My input is

<root> <ahead>first head</ahead> <x>som text</x> <s>some text</s> <b>some text</b> <k>some text</k> <ahead>first head</ahead> <s>some text</s> <b>some text</b> <k>some text</k> <j>some text</j> </root>

Output

<root> <aheadtext> <ahead>first head</ahead> <x>som text</x> <s>some text</s> <b>some text</b> <k>some text</k> </aheadtext> <aheadtext> <ahead>second head</ahead> <s>some text</s> <b>some text</b> <k>some text</k> <j>some text</j> </aheadtext> </root>
I got the sibling nodes by following code
$t->parse($content); @sib = $t->get_xpath('//ahead', 0)->next_siblings();

I got all siblings in @sib including second ahead and its data. How to add the condition in next_siblings() to get the first ahead contents only?

Thanks,

Aakikce

Replies are listed 'Best First'.
Re: XML::Twig - extracting some tags from siblings
by mirod (Canon) on Jun 05, 2007 at 12:36 UTC

    You can't do that with a simple condition. The simplest is probably to do something like (untested):

    my @sheads= $t->root->children( 'shead'); foreach my $shead (@sheads) { my $aheadtext= $shead->wrap_in( 'aheadtext'); my $more_text= $aheadtext->next_sibling; while( $more_text->tag ne 'shead') { $more_text->move( last_child => $aheadtext); $more_text= $aheadtext->next_sibling; } }

      Hi Mirod,

      Thanks for your reply. what you have given is exactly correct.

      But I am struggling with the 'while' loop. I tested with the 'if' loop many times, it runs properly. In 'while' loop I get error as can't call method tag.

      if ($more_text->tag ne "ahead") { $more_text->move(last_child => $aheadtext); $more_text = $aheadtext->next_sibling; } if ($more_text->tag ne "ahead") { $more_text->move(last_child => $aheadtext); $more_text = $aheadtext->next_sibling; }

      Can you please explain.

      thanks,

      AAkikce

        I told you it was untested! ;--)

        Of course at some point you get to the last child, and $aheadtext->next_sibling; doesn't exist, so $more_text becomes undef.

        So the test should not be while( $more_text->tag ne 'shead'), which will die when you trying to call the tag method on the undef value in $more_text, but while( $more_text && ($more_text->tag ne 'shead')).

        Does that help?