注销上下文节点作用域中的命名空间



我使用的是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.xss的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'

这是Perl绑定的一个限制。XML::LibXML总是在上下文节点的作用域中注册所有名称空间。您所能做的就是将现有前缀重新绑定到另一个命名空间,就像您在问题的编辑部分所做的那样。如果您删除对unregisterNS的调用,它应该执行您想要的操作:

$xpc2->registerNs('bar', 'nothing'); # Rebind prefix
my @nodes = $xpc2->findnodes('bar:id', $par);
print scalar(@nodes), "n"; # Prints 0

是因为bar命名空间尚未注册吗?如果我在unregisterNs调用之前添加$xpc2->registerNs('bar', 'www.bar.com');,程序对我来说运行得很好。这会产生你想要的行为吗?

根据附加信息更新:进行查询的方式可能会暴露出libxml或XML::libxml中的错误;我对XPathContext不够熟悉,不知道它是否是一个bug。所以我尝试了一些让我困惑的东西,在我做了unregisterNS之后,我做了一个lookupNS,我仍然得到了正确的NS:

$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命令。

相关内容

  • 没有找到相关文章

最新更新