我正在使用 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'