http://www.perlmonks.org?node_id=1043164


in reply to Re^4: How to parse xml with namespase vale in XMl:LibXML? (xmllint --shell setns / xpathtester)
in thread How to parse xml with namespase value in XMl:LibXML?

Hi Choroba,

Thanks a lot and sorry for being stupid. Actually, my objective was to get values of "xlink:href" and "xlink:title" for first occurrence of "book:locator" in Xpath context.

Any hint or tweak on that?
  • Comment on Re^5: How to parse xml with namespase vale in XMl:LibXML? (xmllint --shell setns / xpathtester)

Replies are listed 'Best First'.
Re^6: How to parse xml with namespase vale in XMl:LibXML? (xmllint --shell setns / xpathtester)
by choroba (Cardinal) on Jul 08, 2013 at 20:30 UTC
    To use namespaces in the full depth, use XML::LibXML::XPathContext:
    #!/usr/bin/perl use warnings; use strict; use XML::LibXML; my $xpc = XML::LibXML::XPathContext->new(); my $xml = XML::LibXML->load_xml(IO => *DATA); my $root = $xml->documentElement; $xpc->registerNs('xlink', 'http://www.w3.org/1999/xlink'); my $chapter_node = $xpc->findnodes('book:chapter', $root)->[0]; print $xpc->findvalue('book:locator/@xlink:title | book:locator/@xlink +:href', $chapter_node) . "\n";
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Probably ought to store the context in the ROOT, oh well

      #!/usr/bin/perl -- use strict; use warnings; use XML::LibXML; use Data::Dump qw/ dd pp /; Main( @ARGV ); exit( 0 ); sub ROOTNS { my( $self ) = @_; $::xpcroot = ROOT( $self ); $::xpc = XML::LibXML::XPathContext->new( ); for my $node ( $::xpcroot->F('//*') ){ for my $att( $node->attributes() ){ if( $att->isa( "XML::LibXML::Namespace" ) ){ my $suffix = $att->localname; my $value = $att->value; print '# autoRegisterNs( ', pp( $suffix ), ' => ', pp( + $value ) , " );\n"; $::xpc->registerNs( $suffix => $value ); } } } } sub ROOT { my( $self ) = @_; my $parent = $self; while( my $newparent = $parent->getParentNode ){ $parent = $newparent; } return $parent; } BEGIN { $::xpc = XML::LibXML::XPathContext->new(); sub XML::LibXML::Node::F { my( $self, $xpath, $context ) = @_; unless( $::xpcroot and $::xpcroot == ROOT( $self ) ){ ROOTNS( $self ); } $::xpc->findnodes( $xpath, $context || $self ); } } sub Main { my $dom = XML::LibXML->new( qw/ recover 2 / )->load_xml( string => q{<?xml version="1.0" ?> <book xmlns:book="http://generated.ns/book" xmlns:xlink="http://www.w3 +.org/1999/xlink"> <book:chapter id="bk444444ch1" type="CHAPTER"> <book:locator xlink:href="/book/isbn/979-0-4444-1000-17/book-part/ +chapter/bk444444ch1?releaseStatus=RELEASED" xlink:title="Photonic cry +stal light-emitting sources" xlink:type="locator"></book:locator> <book:locator xlink:href="/book/isbn/979-0-4444-1000-17/book-part/ +chapter/bk444444ch1?releaseStatus=RELEASED&amp;format=pdf" xlink:titl +e="Photonic crystal light-emitting sources" xlink:type="locator"></bo +ok:locator> <book:locator xlink:href="/book/isbn/979-0-4444-1000-17/book-part/ +chapter/bk444444ch1?releaseStatus=RELEASED&amp;format=epub" xlink:tit +le="Photonic crystal light-emitting sources" xlink:type="locator"></b +ook:locator> </book:chapter> </book>}, ); print $_->nodePath,"\n" for $dom->F(q{//book:locator/@xlink:href}) +; } __END__ # autoRegisterNs( "book" => "http://generated.ns/book" ); # autoRegisterNs( "xlink" => "http://www.w3.org/1999/xlink" ); /book/book:chapter/book:locator[1]/@xlink:href /book/book:chapter/book:locator[2]/@xlink:href /book/book:chapter/book:locator[3]/@xlink:href
        A twist in the smae context. what could be the tweak if we want to caputue values of "xlink:href" and "xlink:title" if "xlink:href" ends with "releaseStatus=RELEASED"?
        FWIW, this autoRegisterNs is completely unneccessary with the xml included in the program, but if you remove   xmlns:book="http://generated.ns/book" xmlns:xlink="http://www.w3.org/1999/xlink" then it becomes neccessary