2

我正在尝试使用 XML::XPath 从 XML 文档中提取内容。文档是用命名空间指定的,但我想使用没有命名空间的 XPath 表达式。据我所知,我在两个不同的脚本中都能正常工作。

似乎今天的某个时候,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
    

    正确的。空命名空间中有一个e元素。

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

    正确的。空命名空间中没有e元素。

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

    不正确。空命名空间中没有e元素,但打印了一个。

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

    不正确。空命名空间中没有e元素,但打印了一个。

  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 回答