为什么这个xmlns属性搞砸了我的xpath查询?

jac*_*ter 1 perl xpath libxml2

我正在使用LibXML解析一个简单的jhove输出.但是,我没有得到我期望的价值.这是代码:

use feature "say";
use XML::LibXML;

my $PRSR = XML::LibXML->new();
my $xs=<DATA>; 
say $xs;
my $t1 = $PRSR->load_xml(string => $xs);
say "1:" . $t1->findvalue('//date');
$xs=<DATA>; 
say $xs;
$t1 = $PRSR->load_xml(string => $xs);
say "2:" . $t1->findvalue('//date');


__DATA__
<jhove xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hul.harvard.edu/ois/xml/ns/jhove" xsi:schemaLocation="http://hul.harvard.edu/ois/xml/ns/jhove http://hul.harvard.edu/ois/xml/xsd/jhove/1.3/jhove.xsd" name="Jhove" release="1.0 (beta 3)" date="2005-02-04"><date>2006-10-06T09:11:34+02:00</date></jhove>
<jhove><date>2006-10-06T09:11:34+02:00</date></jhove>
Run Code Online (Sandbox Code Playgroud)

如您所见,"1:"行返回一个空字符串,而"2:"返回预期日期.jhove-root-element中的什么使xpath查询无法正常工作?我甚至在XML-Spy中尝试过它,即使有完整的标题也可以.

编辑:当我从根元素中删除xmlns属性时,xpath查询工作.但那怎么可能呢?

tob*_*ink 5

XML ::的libxml ::节点的文件明确提到此问题以及如何处理呢?

关于NAMESPACES和XPATH的注意事项:

关于XPath的一个常见错误是假设节点测试由一个没有前缀的元素名称与默认命名空间中的元素匹配.这种假设是错误的 - 通过XPath规范,此类节点测试只能匹配no(即null)命名空间中的元素.

因此,例如,一个人无法匹配XHTML文档的根元素,$node->find('/html')因为'/html'只有在根元素<html>没有命名空间时才匹配,但所有XHTML元素都属于命名空间http://www.w3.org/1999/xhtml.(请注意,xmlns="..."也可以在DTD中指定名称空间声明,这会使情况更糟,因为XML文档看起来好像没有默认名称空间).

有几种可能的方法来处理XPath中的命名空间:

  • 建议的方法是使用XML :: LibXML :: XPathContext模块为XPath评估定义显式上下文,其中可以定义文档无关的前缀到命名空间映射.例如:

    my $xpc = XML::LibXML::XPathContext->new;
    $xpc->registerNs('x', 'http://www.w3.org/1999/xhtml');
    $xpc->find('/x:html',$node);
    
    Run Code Online (Sandbox Code Playgroud)
  • 另一种可能性是使用在查询文档中声明的前缀(如果已知).如果文档声明了所讨论的命名空间的前缀(并且上下文节点在声明的范围内),则XML :: LibXML允许您在XPath表达式中使用前缀,例如:

    $node->find('/x:html');
    
    Run Code Online (Sandbox Code Playgroud)