【问题标题】:XPath query for attributes containing a namespace prefix包含命名空间前缀的属性的 XPath 查询
【发布时间】:2014-02-27 19:20:10
【问题描述】:

我正在尝试在 Perl 中使用 XML::XPath 查询 XML 文档,但是当元素的属性名称包含命名空间前缀时,我遇到了问题。

示例 XML:

<root xmlns="root-ns" xmlns:cat="urn:oasis:names:tc:entity:xmlns:xml:catalog"     xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="A" schematron-version="1.0" xsi:schemaLocation="some location">
  <elementA id="elementA">
    <ElementA-1>
      <ElementA-1-1 id="ElementA-1-1" xlink:href="#ElementA-1-1">
        <cat:catalog>
          <cat:uri name="name" uri="#something"/>
        </cat:catalog>
      </ElementA-1-1>
    </ElementA-1>
  </elementA>
</root>

我的查找查询如下所示:

if ($nodeset = $nodes->find("/root/elementA[\@id='elementA']/ElementA-1/ElementA-1-1[\@xlink:href='#ElementA-1-1']/cat:catalog/cat:uri/\@uri") {
  print "nodeset found.\n";
}
else {
  print "no nodeset found.\n";
}

当我对示例 XML 文档运行此操作时,XPath 抱怨 @xlink:href 属性名称中的 ':',但我无法在查询中找到引用此属性的正确方法。任何帮助将不胜感激!

【问题讨论】:

    标签: xml perl xpath


    【解决方案1】:

    由于括号不匹配,您问题中的 Perl 代码无法编译。

    如果我解决了这个问题并交换单引号和双引号(这样就不需要转义任何内容),那么您的 XPath 表达式就可以正常工作。

    请注意,您有一个非常具体的 XPath 字符串,很少需要对您感兴趣的节点的路径内容如此明确。只需 //cat:uri/@uri 就可以完成这项工作。

    use strict;
    use warnings;
    
    use XML::XPath;
    
    my $xp = XML::XPath->new(xml => <<'END');
    <root xmlns="root-ns" xmlns:cat="urn:oasis:names:tc:entity:xmlns:xml:catalog"     xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="A" schematron-version="1.0" xsi:schemaLocation="some location">
      <elementA id="elementA">
        <ElementA-1>
          <ElementA-1-1 id="ElementA-1-1" xlink:href="#ElementA-1-1">
            <cat:catalog>
              <cat:uri name="name" uri="#something"/>
            </cat:catalog>
          </ElementA-1-1>
        </ElementA-1>
      </elementA>
    </root>
    END
    
    
    my $nodeset = $xp->find('/root/elementA[@id="elementA"]/ElementA-1/ElementA-1-1[@xlink:href="#ElementA-1-1"]/cat:catalog/cat:uri/@uri');
    
    for my $node ($nodeset->get_nodelist) {
      printf "Name:  %s\n",  $node->getName;
      printf "Value: %s\n",  $node->getValue;
    }
    

    输出

    Name:  uri
    Value: #something
    

    【讨论】:

    • 感谢您的回复,这有助于向我表明我并没有发疯,并且我的实际代码应该可以工作,尽管我在上面的示例中捏造了。我发现了我的问题。我在实际内容中使用了错误的元素名称。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    相关资源
    最近更新 更多