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;
}
未テスト。