如何测试节点是否包含命名空间

时间:2016-08-11 11:07:22

标签: xml perl xpath

鉴于下面的XML片段,我如何区分

<entry xmlns:georss="...">

与孩子一起

<title>fileName1.jpg</title> 

<entry><title type="text">fileName.pdf</title></entry>

我正在使用XML::LibXML循环浏览<entry>,但这会获得每个<type> <link><entry>之间的联系。我需要在<type>级别测试,而不是在<type>级别

您可以测试入口节点是否具有georss namespace?

这样的东西得到foreach my $Entry ($dom->findnodes("//dft:feed/dft:entry")) { foreach my $Images ($dom->findnodes("//dft:title[not(\@type='text')]", $Entry)) { my $ImageVal = $Images->textContent; #### This finds all the Images } }

的值
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:georss="http://www.georss.org/georss">

  <entry xmlns:georss="http://www.georss.org/georss/10" xsi:schemaLocation ="http://www.url1.net/path/ http://www.url2.net/path/11  http://www.url3.net/path/23" >
    <title>fileName1.jpg</title>
    <link href="PathTo/fileName1.jpg" />
  </entry>

  <entry xmlns:georss="http://www.georss.org/georss/10" xsi:schemaLocation ="http://www.url1.net/path/ http://www.url2.net/path/11  http://www.url3.net/path/23" >
    <title>fileName2.jpg</title>
    <link href="PathTo/fileName2.jpg" />
  </entry>

  <entry>
    <title type="text">fileName.pdf</title>
    <link type="application/pdf"  href="PathTo/fileName.pdf" />
  </entry>

</feed>

XML代码段

.content {
  position: static;
}

.header {
  text-align: center;
  position: relative;
  margin-top: 40px;
}

th, td { 
  border:1px solid black;
  overflow: hidden;
}

th {
  background-color: #eff0f0;
}

td {
  background-color: #eed6b1;
  height: 45px;
}

tr:nth-child(even) td {
  background-color: #FFF1E1;
}

table {
  table-layout: fixed;
  min-width: 2000px;
  border-collapse: collapse;
  width: 100%;
  margin-left: 5px;
}

.DZ {
  text-align: center;
}


tr:hover td {
  background-color: #ccc;
}

tr:nth-child(even) {
  background-color: #e5e5e5;
}

tr td {
  border-right: 1px solid #a5a5a5;
}

.Bezborder {
  border-right: 1px solid black;
}

.ht:hover .tooltip {
  display: block;
}

.tooltip {
  position:absolute;
  display: none;
  background-color: #fafbb8;
  border: 1px solid black;
  border-radius: 4px;
  margin-left: 28px;
  padding: 10px;
  position:absolute;
  z-index: 1000;
  width: 680px;
  height: 50px;
  font-weight: bold;
}

1 个答案:

答案 0 :(得分:1)

  

您可以测试入口节点是否有georss命名空间?

您的示例中没有georss命名空间中的数据。一切都在http://www.w3.org/2005/Atom元素中定义的名称空间feed中。定义xmlns:georss="http://www.georss.org/georss/10"仅指定名称空间前缀georss,但该前缀从不使用

您需要创建一个XML::LibXML::XPathContext对象,该对象附加到XML::LibXML文档,允许您指定命名空间缩写。代码如下所示

请注意,我还必须修复您的XML数据以包含xsi命名空间的定义,因为没有它,数据格式不正确

您不应该养成在每个XPath表达式的开头添加//的习惯。它强制XPath引擎每次都不必要地搜索整个文档,并且从根目录中显式的XPath是更好的做法。它还会使用XPath //dft:title[not(@type='text')]生成错误的结果,因为您每次都从根开始搜索并忽略entry上下文节点。只是dft:title[not(@type="text")]是正确的

use strict;
use warnings 'all';

use XML::LibXML;
use XML::LibXML::XPathContext;

my $dom = XML::LibXML->load_xml( location => 'feed.xml' );

my $xpc = XML::LibXML::XPathContext->new($dom);
$xpc->registerNs( dft    => 'http://www.w3.org/2005/Atom' );
$xpc->registerNs( georss => 'http://www.georss.org/georss/10' );

for my $entry ($xpc->findnodes('/dft:feed/dft:entry')) {

     for my $images ($xpc->findnodes('dft:title[not(@type="text")]', $entry)) {

         my $image_val = $images->textContent;

         print $image_val, "\n";
     }
}

输出

fileName1.jpg
fileName2.jpg