Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath variables in XML::Twig or Other

I'm using XML::Twig::XPath to work with ITS data, and am trying to figure out how to resolve XPath expressions with variables in them. Here's an example of what I need to work with from the ITS spec:

<its:rules version="2.0">
  <its:param name="LCID">0x0409</its:param>
  <its:translateRule selector="//msg[@lcid=$LCID]" translate="yes"/>
</its:rules>

I need to be able to evaluate the XPath expression contained in selector, with the value of the variable being the contents of the its:param element. I am at a loss as to how to do this. The documentation of XML::XPath mentions variables (which I assume should be part of the context), and it even has a class to represent them, but the documentation doesn't say how to specify variables in a context. I would be even more unsure of how to access such functionality from XML::Twig, if at all possible.

Does anyone know how to do this? Or alternatively, can you give an example of how to use such functionality with another module such as XML::LibXML (which mentions variables extensively, but leaves me a little unsure as to how to do this with variables that are strings)?

like image 819
Nate Glenn Avatar asked Mar 23 '23 10:03

Nate Glenn


1 Answers

libxml2 and XML::LibXML supports XPath 2.0 paths and their variables.

use XML::LibXML               qw( );
use XML::LibXML::XPathContext qw( );

sub dict_lookup {
   my ($dict, $var_name, $ns) = @_;
   $var_name = "{$ns}$var_name" if defined($ns);
   my $val = $dict->{$var_name};
   if (!defined($val)) {
      warn("Unknown variable \"$var_name\"\n");
      $val = '';
   }

   return $val;
}

my $xml = <<'__EOI__';
<r>
<e x="a">A</e>
<e x="b">B</e>
</r>
__EOI__

my %dict = ( x => 'b' );

my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($xml);

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerVarLookupFunc(\&dict_lookup, \%dict);

say $_->textContent() for $xpc->findnodes('//e[@x=$x]', $doc);
like image 67
ikegami Avatar answered Mar 25 '23 23:03

ikegami