【问题标题】:ruby libxml : Where does returned node value come from?ruby libxml:返回的节点值来自哪里?
【发布时间】:2015-11-08 00:20:10
【问题描述】:

在 Ruby 中使用 libxml 解析 XML 文档时,我从 find XPath 调用中收到了太多数据。

我的测试数据是:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<MAIN>
  <EPS>
    <EP ID="EDM01">EP 1
      <BP ID="EDM01_BP1">BP1 for EP1
        <Activities>
          <Activity ID="1">Activity 1 for EDM01_BP1</Activity>
          <Activity ID="2">Activity 2 for EDM01_BP1</Activity>
          <Activity ID="3">Activity 3 for EDM01_BP1</Activity>
        </Activities>
      </BP>
      <BP ID="EDM01_BP2">BP2 for EP1
         <Activities>
           <Activity ID="1">Activity 1 for EDM01_BP2</Activity>
           <Activity ID="2">Activity 2 for EDM01_BP2</Activity>
           <Activity ID="3">Activity 3 for EDM01_BP2</Activity>
         </Activities>
      </BP>
    </EP>
    <EP ID="APO01">EP 2
      <BP ID="APO01_BP1">BP 1 for EP2
        <Activities>
          <Activity ID="1">Activity 1 for APO01_BP1</Activity>
          <Activity ID="2">Activity 2 for APO01_BP1</Activity>
          <Activity ID="3">Activity 3 for APO01_BP1</Activity>
          <Activity ID="4">Activity 4 for APO01_BP1</Activity>
          <Activity ID="5">Activity 5 for APO01_BP1</Activity>
        </Activities>
      </BP>
    </EP>
  </EPS>
</MAIN>

我解析它:

xmlparser = XML::Parser.string(@strXML,:encoding => XML::Encoding::UTF_8)
@xmlDoc = xmlparser.parse
@projects = nil
project = nil
cl = @xmlDoc.find('/MAIN')
unless (cl.empty?)
  puts ""
  @projects = @xmlDoc.find('//EP [@ID]')
  @projects.each do |p|
    puts('<----------1--------->')
    puts(p.inner_xml)
    bps = p.find('//BP [@ID]')
    bps.each do |bp|
      puts('<----------2--------->')
      puts(bp.inner_xml)
      puts('<---- Activities ---->')
      acts = bp.find('//Activity [@ID]')
      acts.each do |act|
        puts('ActID> ' + act['ID'].to_s)
        puts(act.first.content.to_s)
      end
    end
  end
end
assert true
end

查看显示结果时,显示获取的xml::node是正确的(p.inner_xml)

<----------1--------->
EP 1      <BP ID="EDM01_BP1">BP1 for EP1<Activities><Activity ID="1">Activity 1 for EDM01_BP1</Activity><Activity ID="2">Activity 2 for EDM01_BP1</Activity><Activity ID="3">Activity 3 for EDM01_BP1</Activity> </Activities></BP><BP ID="EDM01_BP2">BP2 for EP1<Activities><Activity ID="1">Activity 1 for EDM01_BP2</Activity><Activity ID="2">Activity 2 for EDM01_BP2</Activity><Activity ID="3">Activity 3 for EDM01_BP2</Activity>         </Activities></BP>  
<----------2--------->
BP1 for EP1<Activities><Activity ID="1">Activity 1 for EDM01_BP1</Activity>          <Activity ID="2">Activity 2 for EDM01_BP1</Activity><Activity ID="3">Activity 3 for EDM01_BP1</Activity></Activities>
<---- Activities ---->  
ActID> 1  
Activity 1 for EDM01_BP1  
ActID> 2  
Activity 2 for EDM01_BP1  
ActID> 3  
Activity 3 for EDM01_BP1  
ActID> 1  
Activity 1 for EDM01_BP2  
ActID> 2  
Activity 2 for EDM01_BP2  
ActID> 3  
Activity 3 for EDM01_BP2  
ActID> 1  
Activity 1 for APO01_BP1  
ActID> 2  
Activity 2 for APO01_BP1  
ActID> 3  
Activity 3 for APO01_BP1  
ActID> 4  
Activity 4 for APO01_BP1  
ActID> 5  
Activity 5 for APO01_BP1  

如您所见,第一个 XML 节点只检查了 3 个活动。 但是该程序会显示完整 xml 文档中的所有活动。不仅来自获取的节点。

当做一个 xmldoc.find() 并用它遍历它时,这是一个错误的假设吗? 节点。每个都做|n| n 变量是一个 libXML::XML::Node,它是 xml 文档的一个子集? 否则怎么可能引用不属于获取节点的数据(活动 APOxxx)?

【问题讨论】:

  • 将查找语句更改为“活动/活动 [@ID]”“解决”了问题,但不是问题。在我看来,xml 文档的子集(获取的节点)可以返回整个文档的一部分是不正确的。

标签: ruby libxml2 xpath-2.0


【解决方案1】:

替换行

bps = p.find('//BP [@ID]')
acts = bp.find('//Activity [@ID]')

bps = p.find('BP [@ID]')
acts = bp.find('Activities/Activity [@ID]')

/// 开头的XPath 表达式为absolute location paths,并且无论上下文节点pbp 为何,始终返回根节点下的所有匹配节点。这类似于不关心当前目录的绝对文件系统路径。

【讨论】:

  • 谢谢。但是,这意味着根据您的示例,当我们将目录称为新的“根”时,仍然可以引用“旧根”。据我所知,使用 ruby​​ 构造 nodes.each do |node| 遍历使用 xpath 查询检索到的 xml 文档选择不会返回 XML 节点变量作为引用节点的 inner_xml 的副本。
猜你喜欢
  • 1970-01-01
  • 2012-11-07
  • 2012-01-03
  • 2021-11-21
  • 2010-12-09
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多