【问题标题】:Perl and Xpath: considering hierarchyPerl 和 Xpath:考虑层次结构
【发布时间】:2014-10-26 22:13:43
【问题描述】:

考虑到层次结构,我想提取 XML 的属性值:

<?xml version="1.0" encoding="UTF-8"?>
<database>
  <row1s>
   <row1 name="fox" category="mammal">
       <row2s>
         <row2 type="1"/>
         <row2 type="2"/>
       </row2s>
   </row1>
   <row1 name="horse" category="mammal">
       <row2s>
         <row2 type="3"/>
       </row2s>
   </row1>
   <row1 name="bee" category="insect"> 
       <row2s/>
   </row1>
   <row1 name="wasp" category="insect">
       <row2s/>
   </row1>
  </row1s>
</database>

这是我提取值的 Perl 代码:

use strict;
use DBI;
use XML::XPath;
use XML::XPath::XMLParser;

my $xrow1;
my $xrow2;

my $xp = XML::XPath->new (filename => "animals3.xml");

my $node_list1 = $xp->find ("//row1s/row1");

foreach my $row1 ($node_list1->get_nodelist ())  {
    $xrow1 = $row1->getAttribute("name");
    print "Level row1 gives: $xrow1\n";

    my $node_list2 = $xp->find ("//row2s/row2");

    foreach my $row2 ($node_list2->get_nodelist ()) {
    $xrow2 = $row2->getAttribute("type");    
    print "Level row2 gives: $xrow2\n";
    }
}

我得到的是:

Level row1 gives: fox   
Level row2 gives: 1   
Level row2 gives: 2   
Level row2 gives: 3   
Level row1 gives: horse   
Level row2 gives: 1   
Level row2 gives: 2   
Level row2 gives: 3   
Level row1 gives: bee   
Level row2 gives: 1   
Level row2 gives: 2   
Level row2 gives: 3   
Level row1 gives: wasp   
Level row2 gives: 1   
Level row2 gives: 2   
Level row2 gives: 3   

对于每个级别 1,我从级别 2 获取所有属性值。这不是我想要的。我想只输出通讯员级别 1 的级别 2 条目。但我想要的是:

Level row1 gives: fox   
Level row2 gives: 1   
Level row2 gives: 2   
Level row1 gives: horse   
Level row2 gives: 3   
Level row1 gives: bee   
Level row1 gives: wasp   

我将不胜感激任何提示如何解决这个问题。

谢谢。

【问题讨论】:

    标签: perl xpath xml-parsing hierarchy


    【解决方案1】:

    前导/ 表示绝对路径。

    my $node2 = $xp->find("//row2s/row2");
    

    应该是

    my $node2 = $xp->find("row2s/row2", $row1);
    

    评论:

    • $node1$node2 都不是节点。选择更好的名字。

    • 在你所做的地方声明你的变量部分违背了声明它们的目的。它们应该在适当的循环中声明。

    【讨论】:

    • 非常感谢您的回答。我按照您的建议更改了线路。输出现在仅给出来自级别 1(狐狸、马、蜜蜂、黄蜂)的属性值,而没有对应的级别 2 值。如果 $node1 不是节点,它是什么? $element1 会更好吗?还是 $level1?
    • $node1_list$animals 是两种可能性。测试
    • 哦,这是因为您的 XML 没有意义。尽管您的缩进暗示其他情况,但 row1 元素都没有 row2s 子元素。我认为您的意思是使用 &lt;row1 name="fox" category="mammal"&gt;&lt;row2s&gt;&lt;row2 type="1"/&gt;&lt;row2 type="2"/&gt;&lt;/row2s&gt;&lt;/row1&gt; 您是否可以修复 XML,或者您是否需要与您现有的代码一起使用的代码?
    • $xrow1$xrow2
    • 关于“我想知道在哪里可以收集这些信息”,我通过阅读spec 学习了 XPaths。按照规格,它很轻。不过,这可能并不适合所有人。
    【解决方案2】:

    以下修复并简化了您的脚本:

    use strict;
    use warnings;
    
    use XML::XPath;
    use XML::XPath::XMLParser;
    
    #my $xp = XML::XPath->new( filename => "animals3.xml" );
    my $xp = XML::XPath->new( ioref => \*DATA );
    
    for my $row1 ( $xp->findnodes('//row1s/row1') ){
        printf "Level row1 gives: %s\n", $row1->getAttribute("name");
    
        for my $row2 ( $row1->findnodes('.//row2s/row2') ) {
            printf "Level row2 gives: %s\n", $row2->getAttribute("type");
        }
    }
    
    __DATA__
    <?xml version="1.0" encoding="UTF-8"?>
    <database>
      <row1s>
       <row1 name="fox" category="mammal">
           <row2s>
             <row2 type="1"/>
             <row2 type="2"/>
           </row2s>
       </row1>
       <row1 name="horse" category="mammal">
           <row2s>
             <row2 type="3"/>
           </row2s>
       </row1>
       <row1 name="bee" category="insect"> 
           <row2s/>
       </row1>
       <row1 name="wasp" category="insect">
           <row2s/>
       </row1>
      </row1s>
    </database>
    

    输出:

    Level row1 gives: fox
    Level row2 gives: 1
    Level row2 gives: 2
    Level row1 gives: horse
    Level row2 gives: 3
    Level row1 gives: bee
    Level row1 gives: wasp
    

    【讨论】:

    • 非常感谢。我学到了一些新的技巧。如果您能看看我的后续问题,我将不胜感激:link
    • 很高兴我能帮上忙。我看了你的新问题,但我发现鲍罗丁在帮助方面已经做了足够的工作。
    猜你喜欢
    • 1970-01-01
    • 2014-07-14
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 2015-01-09
    • 2012-12-10
    • 1970-01-01
    相关资源
    最近更新 更多