3

XML::LibXML を使用しています。XPath コンテキストを作成する際には、使用可能な名前空間を正確に指定できる必要があります。ただし、コンテキスト ノードのスコープ内のすべての名前空間は、XPathContext オブジェクトに自動的に登録されます。それらを登録解除する必要がありますが、コンテキスト ノードのスコープ内にある名前空間を登録解除しようとするとエラーが発生します。

use XML::LibXML;
use XML::LibXML::XPathContext;

my $xml = <<'__EOI__';
<?xml version="1.0"?>
<myDoc id="myDocId">
    <body id="bodyId">
    <baz:par xmlns:baz="www.baz.com"
             xmlns:bar="www.bar.com">
        <bar:id>xyz123</bar:id>
    </baz:par>
    </body>
</myDoc>
__EOI__

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

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs('baz', 'www.baz.com');

my $par = ${ $xpc->findnodes('//baz:par', $doc) }[0];

my $xpc2 = XML::LibXML::XPathContext->new($par);
$xpc2->unregisterNs('bar');

上記の鳴き声XPathContext: cannot unregister namespace。ソースを調べると、LibXML.xsの 7618 行目からエラーが出力されていることがわかります。関数xmlXPathRegisterNsが -1 を返したときに出力されます。私が見つけることができるこの関数の唯一のドキュメントはxmlsoft.orgにあります。このドキュメントでは、-1 の戻り値はエラーが発生したことを意味すると明記されていますが、エラーが発生する条件については明記されていません。私は一生、その方法のソースを見つけることができません。

XPath 仕様ではこの特定の操作が許可されていない可能性が非常に高いですが、それを判断することもできません。

a) XML::LibXML::XPathContext を使用してコンテキスト ノードのスコープ内の名前空間を登録解除する方法があるかどうか、または b) これが XPath で許可されていないというドキュメントがある場合は、誰にでも教えてもらえますか?

編集

Joel は、名前空間を手動で登録していない場合にのみ、名前空間の登録を解除すると特定のエラーがスローされることを示しました。ただし、登録解除はまだ正しく機能しません。

$xpc2->registerNs('bar', 'nothing'); #otherwise unregistering throws an error
$xpc2->unregisterNs('bar');
my @nodes = $xpc2->find('bar:id');
print scalar @nodes; #I want '0', but this prints '1'
4

2 に答える 2

0

名前空間がbarまだ登録されていないからでしょうか。$xpc2->registerNs('bar', 'www.bar.com');呼び出しの直前に追加するunregisterNsと、プログラムは正常に実行されます。これにより、必要な動作が生成されますか?

追加情報からの更新: クエリの実行方法によって、libxml または XML::LibXML のバグが明らかになる場合があります。XPathContext がバグかどうかを知るには、XPathContext に精通していません。だから私は私を混乱させる何かを試しましlookupNSunregisterNS.

$xpc2->registerNs('bar', 'www.bar.com');
$xpc2->unregisterNs('bar');
print $xpc2->lookupNs('bar') . "\n"; # print www.bar.com

ただし、探していることを実行するソリューションがある場合があります。代わりに使用'bar'しようとした接頭辞として使用する'bob'代わりに、探している動作が得られる可能性があると思います。

$xpc2->registerNs('bob', 'www.bar.com');
$xpc2->unregisterNs('bob');
my @nodes = $xpc2->find('bob:id');
print scalar @nodes . "\n";

このようにすると、findメソッドは例外をスローします。print scalarコードはコマンドに到達しません。

于 2013-07-16T22:05:22.227 に答える