Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re^3: XML::Twig not finding an element's parent's text

by choroba (Cardinal)
on May 18, 2025 at 18:44 UTC ( [id://11165058]=note: print w/replies, xml ) Need Help??


in reply to Re^2: XML::Twig not finding an element's parent's text
in thread XML::Twig not finding an element's parent's text

> That sounded promising but has no effect. Whether before or after the selected element, the text is not available.

I probably wasn't clear enough. This was not an advice how to solve the problem, it was an attempt to show you how Twig behaves.

#!/usr/bin/perl use warnings; use strict; use XML::Twig; my $xml = XML::Twig->new( twig_handlers => { 'text:bookmark' => \&handler_bookmark } ); $xml->parse(\*DATA); print qq(\n\n); # $xml->print; exit(0); sub handler_bookmark { my ($twig, $bookmark)= @_; $bookmark->parent->print; } __DATA__ <?xml version="1.0" encoding="UTF-8"?> <text:h text:style-name="P900" text:outline-level="3"> BEFORE<text:bookmark text:name="_asdfqwerzxcv"/>Foo bar </text:h>
Output:
<text:h text:outline-level="3" text:style-name="P900"> BEFORE<text:bookmark text:name="_asdfqwerzxcv"/></text:h>
See? "BEFORE" is there, while "Foo bar" is not.

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re^4: XML::Twig not finding an element's parent's text
by mldvx4 (Friar) on May 19, 2025 at 18:44 UTC

    Thanks. Working with parent elements containing the target element was the way to go, rather than aiming directly at the target element itself. See the first handler below.

    There are a lot of handlers in this script, but here are a pair relevant to my original question:

    my $xml = XML::Twig->new( pretty_print => 'nsgmls', # nsgmls for parsability output_encoding => 'UTF-8', twig_roots => { 'office:body' => 1 }, twig_handlers => { # link anchors (text:boomark) must be handled before # processing the internal links '*[text:bookmark]' => \&handler_bookmark, . . . $xml = XML::Twig->new( pretty_print => 'nsgmls', empty_tags => 'html', output_encoding => 'UTF-8', twig_roots => { 'office:body' => 1 }, twig_handlers => { # links (text:a) must be handled separately from link targets 'text:a' => \&handler_links, . . . sub handler_bookmark { my ($twig, $bookmark)= @_; my @bmk = $bookmark->children('text:bookmark'); foreach my $bk (@bmk) { my $l = $bk->trimmed_text; my $t = $l; $t =~ s/\s/_/g; my $anchor = $bk->att('text:name'); $bookmarks{$anchor}{'label'} = $l; $bookmarks{$anchor}{'target'} = $t; $bk->set_text("\n { ".$anchor.' }'); $bk->parent->merge($bk); } } sub handler_links { my ($twig, $link)= @_; my $href = $link->att('xlink:href'); $href =~ s/^\#//; my $l = $bookmarks{$href}{'label'}; my $t = $bookmarks{$href}{'target'}; if (! $l) { $l = $link->trimmed_text; $link->set_text("[$href $l]\n"); } else { $link->set_text("[$t $l]\n"); } $link->parent->merge($link); } . . .

    These two handler subroutines are each used in separate parsing pass, for a total of two passes. Strangely, two parsings seems to be faster than one pass with all the handlers in a single object. The first pass collects a hash of link targets and their labels. The second pass applies those to the links pointing at those targets.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11165058]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2025-06-21 13:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.