You modify the document with every cut'n'paste—the
<label> are direct children of the
<fig> element the first time, but then the first label becomes a grandchild of
<fig>! Of course, you get the error
Can't call method "cut" on an undefined value when you try to get the
$c'th element from the list containing only one label.
This error appeared because you chose an extremely ineffective way—you call get_xpath on every element in the list instead of fetching all elements once.
The corected variant of your code:
#!/usr/bin/perl
use warnings;
use strict;
use XML::Twig;
my $twig = new XML::Twig(
pretty_print => 'indented',
);
$twig->parse(<<'XML');
<?xml version="1.0"?>
<article>
<label>here label for testing</label>
<fig id="fig001" position="float"><label>Fig. 1.</label><caption><p>fi
+rst</p></caption></fig>
<fig id="fig002" position="float"><label>Fig. 2.</label><caption><p>se
+cond</p></caption></fig>
<fig id="fig003" position="float"><label>Fig. 3.</label><caption><p>th
+ird</p></caption></fig>
<fig id="fig004" position="float"><label>Fig. 4.</label><caption><p>fo
+urth</p></caption></fig>
<fig id="fig005" position="float"><label>Fig. 5.</label><caption><p>fi
+fth</p></caption></fig>
<fig id="fig006" position="float"><label>Fig. 6.</label><caption><p>si
+xth</p></caption></fig>
</article>
XML
my $count = $twig->get_xpath('/article/fig//label');
for my $c (0..($count-1))
{
my $t = $twig->get_xpath('/article/fig/label', 0); #//f
+ig/label -here problem comes
my $pl = $twig->get_xpath('/article/fig//caption', $c);
my $cut = $t->cut ;
$cut->paste('first_child', $pl) ;
+
}
$twig->print;
The more efficient and clean way resulting in the same output:
#!/usr/bin/perl
use warnings;
use strict;
use XML::Twig;
my $twig = new XML::Twig(
pretty_print => 'indented',
);
$twig->parse(<<'XML');
<?xml version="1.0"?>
<article>
<label>here label for testing</label>
<fig id="fig001" position="float"><label>Fig. 1.</label><caption><p>fi
+rst</p></caption></fig>
<fig id="fig002" position="float"><label>Fig. 2.</label><caption><p>se
+cond</p></caption></fig>
<fig id="fig003" position="float"><label>Fig. 3.</label><caption><p>th
+ird</p></caption></fig>
<fig id="fig004" position="float"><label>Fig. 4.</label><caption><p>fo
+urth</p></caption></fig>
<fig id="fig005" position="float"><label>Fig. 5.</label><caption><p>fi
+fth</p></caption></fig>
<fig id="fig006" position="float"><label>Fig. 6.</label><caption><p>si
+xth</p></caption></fig>
</article>
XML
my @labels = $twig->get_xpath('/article/fig/label');
my @captions = $twig->get_xpath('/article/fig/caption');
for my $i (0..$#labels) {
$labels[$i]->move('first_child', $captions[$i]);
}
$twig->print;
But i myself would prefer to let twig_handlers do the job:
#!/usr/bin/perl
use warnings;
use strict;
use XML::Twig;
my $twig = new XML::Twig(
twig_handlers => {
'/article/fig' => sub {
my $label = $_->first_child('label') or return;
my $caption = $_->first_child('caption') or return;
$label->move('first_child', $caption);
$_->flush;
}
},
pretty_print => 'indented',
);
$twig->parse(<<'XML');
<?xml version="1.0"?>
<article>
<label>here label for testing</label>
<fig id="fig001" position="float"><label>Fig. 1.</label><caption><p>fi
+rst</p></caption></fig>
<fig id="fig002" position="float"><label>Fig. 2.</label><caption><p>se
+cond</p></caption></fig>
<fig id="fig003" position="float"><label>Fig. 3.</label><caption><p>th
+ird</p></caption></fig>
<fig id="fig004" position="float"><label>Fig. 4.</label><caption><p>fo
+urth</p></caption></fig>
<fig id="fig005" position="float"><label>Fig. 5.</label><caption><p>fi
+fth</p></caption></fig>
<fig id="fig006" position="float"><label>Fig. 6.</label><caption><p>si
+xth</p></caption></fig>
</article>
XML
$twig->print;
s;;Just-me-not-h-Ni-m-P-Ni-lm-I-ar-O-Ni;;tr?IerONim-?HAcker ?d;print