2

XML::XPath を使用して XML ドキュメントからコンテンツを抽出しようとしています。ドキュメントは名前空間で指定されていますが、名前空間なしで XPath 式を使用したいと考えています。私が知る限り、これは 2 つの異なるスクリプトで完全に正常に機能していました。

今日、XML::XPath の動作がこれに関して変更されたようです。この動作を変更するために何が変更できたのかわかりません。

スクリプトで "set_namespace()" を呼び出し (使用するプレフィックスをハードコーディング)、XPath 式でプレフィックスを指定して、名前空間をほぼ完全に指定すると、いくつかの手動テストを実行できます。

繰り返しますが、スクリプトで「set_namespace()」を呼び出したり、XPath 式でプレフィックスを指定したりしなくても、昨日これが機能していたと確信しています。

その「set_namespace()」呼び出しを追加せず、式でプレフィックスを指定しないと、クエリから空のノードセットを取得するだけです。

最初の XPath オブジェクトを作成する前に、"$XML::XPath::Namespaces" をゼロに設定しようとしましたが、違いはないようです。

以下は、XML をパイプする単純なスクリプトです。

#! /bin/perl
use XML::XPath;
use XML::XPath::XMLParser;
use Getopt::Long;

$| = 1;

my $opt_file;
GetOptions("f|file=s" => \$opt_file);

$XML::XPath::Namespaces = 0;

my $xpath;
if ($opt_file ne '') {
    $xpath = XML::XPath->new(filename => $opt_file);
}
else {
    $xpath = XML::XPath->new(ioref => \*STDIN);
}

while (my $expr = shift @ARGV) {
    my $nodeset = $xpath->find($expr);
    if ($nodeset) {
        if ($opt_file ne '') {
            print $opt_file . ":\n";
        }
        my $node;
        for $node ($nodeset->get_nodelist) {
            print $node->string_value() . "\n";
        }
    }
}

コマンドラインの例を次に示します。

% echo "<ns3:abc xmlns:ns3=\"xxx\"><ns3:def>ghi</ns3:def></ns3:abc>" | xpathtext "//def"

これから「ghi」を得たいと思っていますが、現在何も得られていません。

4

1 に答える 1

1

うわー、そのモジュールはバグです。

あなたの質問はしばらく忘れて、とりあえず$XML::XPath::Namespaces=1;(デフォルト) を使用しましょう。

  1. $ perl -E'say q{<r><e>E</e></r>}' |
       xpathtext //e
    E
    

    正しい。enull 名前空間に要素があります。

  2. $ perl -E'say q{<r xmlns:p="http://n"><p:e>E</p:e></r>}' |
       xpathtext //e
    [nothing]
    

    正しい。enull 名前空間には要素がありません。

  3. $ perl -E'say q{<r xmlns="http://n"><e>E</e></r>}' |
       xpathtext //e
    E
    

    正しくない。enull 名前空間には要素はありませんが、1 つ出力されました。

  4. $ perl -E'say q{<r><e xmlns="http://n">E</e></r>}' |
       xpathtext //e
    E
    

    正しくない。enull 名前空間には要素はありませんが、1 つ出力されました。

  5. $ perl -E'say q{<r xmlns:p="http://n"><p:e>E</p:e></r>}' |
       xpathtext //p:e
    E
    

    正しくない。pXPath でhttp://n名前空間を参照しているかどうかを知る方法がないため、これはエラーになるはずです。

  6. $ perl -E'say q{<r xmlns="http://n"><e>E</e></r>}' |
       xpathtext //p:e
    [nothing]
    

    正しくない。pXPath でhttp://n名前空間を参照しているかどうかを知る方法がないため、これはエラーになるはずです。

このレベルのバグを考えると、問題が発生しても驚くことではありません。


では、 が何をするのかを見てみましょう$XML::XPath::Namespace=0;

上記のプログラムを で再実行すると$XML::XPath::Namespaces=0;、答えは「絶対に何もない」であることがわかります。

変数にマジックを付けることでこれを確認しました。この変数は使用されません (最新バージョンでは XML-XPath-1.13)。

したがって、モジュールの半分はあなたが望むことを行い、半分は本来あるべきことを行いますが、それをカスタマイズする明白な手段はありません。

于 2013-05-21T19:36:29.947 に答える