4

XML::Twig::XPathを使用して ITS データを操作しており、変数を含む XPath 式を解決する方法を見つけようとしています。以下は、ITS仕様で作業する必要があるものの例です。

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

selector要素の内容である変数の値を使用して、 に含まれる XPath 式を評価できる必要がありits:paramます。私はこれを行う方法について途方に暮れています。XML::XPathのドキュメントには、変数 (コンテキストの一部である必要があると思います) が記載されており、それらを表すクラスもありますが、ドキュメントにはコンテキストで変数を指定する方法が記載されていません。可能であれば、XML::Twig からそのような機能にアクセスする方法については、さらに確信が持てません。

誰もこれを行う方法を知っていますか? または、そのような機能を XML::LibXML などの別のモジュールで使用する方法の例を挙げていただけますか (変数については広範囲に言及していますが、文字列である変数でこれを行う方法について少し確信が持てません)。

4

4 に答える 4

2

XPath 1.0 パスのみをサポートするエンジンを使用している場合は、値を次の文法を持つテンプレートとして扱うことができます。

start : parts EOI
parts : part parts |
part  : string_literal | variable | other

以下は、XPath テンプレートから XPath を生成します。

sub text_to_xpath_lit {
   my ($s) = @_;
   return qq{"$s"} if $s !~ /"/;
   return qq{'$s'} if $s !~ /'/;

   $s =~ s/"/", '"', "/g;
   return qq{concat("$s")};
}

my $NCNameStartChar_class = '_A-Za-z\xC0-\xD6\xD8-\xF6\xF8-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}';
my $NCNameChar_class = $NCNameStartChar_class . '\-.0-9\xB7\x{300}-\x{36F}\x{203F}-\x{2040}';
my $NCName_pat = "[$NCNameStartChar_class][$NCNameChar_class]*+";

my $xpath = '';
for ($xpath_template) {
   while (1) {
      if (/\G ( [^'"\$]++ ) /xgc) {
         $xpath .= $1;
      }
      elsif (/\G (?=['"]) /xgc) {
         /\G ( ' [^\\']*+ ' | " [^\\"]*+ " ) /sxgc
            or die("Unmatched quote\n");

         $xpath .= $1;
      }
      elsif (/\G \$ /xgc) {
         /\G (?: ( $NCName_pat ) : )?+ ( $NCName_pat ) /xgc
            or die("Unexpected '\$'\n");

         my ($prefix, $var_name) = ($1, $2);
         my $ns = $ns_map{$prefix}
            or die("Undefined prefix '$prefix'\n");

         $xpath .= text_to_xpath_lit(var_lookup($ns, $var_name));
      }
      elsif (/\G \z /xgc) {
         last;
      }
   }    
}

サンプルvar_lookup:

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

   return $val;
}

未テスト。

于 2013-06-25T05:28:36.240 に答える