新手问题 从一个大的 xml 文件中摘选出一部分内容,但是保持层级结构不变怎么实现

tablecell · 2017年04月29日 · 最后由 theblock24block 回复于 2017年04月29日 · 1669 次阅读

比如 xml 文件中包括了全部的 cpu 和 gpu 型号

<computer>
<cpu>
<item>
<name>Intel Xeon E5-2679 v4 @ 2.50GHz</name>
<frequncy>2.50GHz</frequncy>
</item>
<item>
<name>Intel Core i7-3960X</name>
<frequncy>3.30GHz</frequncy>
</item>
<item>
<name>Intel Core i5-5575R</name>
<frequncy>2.80GHz</frequncy>
</item>
<item>
<name>AMD FX-8140</name>
<frequncy>2.80GHz</frequncy>
</item>
。。。

</cpu>
<gpu>
<item>
<name>GeForce GTX 1080</name>
<benmark>13151</benmark>
</item>

<item>
<name>GeForce GTX 980 Ti</name>
<benmark>11508</benmark>
</item>

<item>
<name>Quadro M6000 24GB</name>
<benmark>11249</benmark>
</item>

<item>
<name>Radeon Pro Duo</name>
<benmark>9164</benmark>
</item>
 。。。
</gpu>

</computer>

文件中包括了全部的 cpu 和 gpu 型号,如果只把其中 cpu 是 amd 和 gpu 是 readeon 的内容摘取出来,保存成一个新的 xml 现在读取可以 rexml 实现

require 'rexml/document'

require 'rexml/streamlistener'

include REXML

class Listener

  include StreamListener

  def tag_start(name, attributes)

    puts "Start #{name}"
    print attributes

  end

  def tag_end(name)

    puts "End #{name}"

  end

end

listener = Listener.new

parser = Parsers::StreamParser.new(File.new("computer.xml"), listener)

parser.parse

如果要保存成新的 xml,但是总体结构不变,应该如何实现?

tablecell 关闭了讨论。 04月29日 10:26
tablecell 重新开启了讨论。 04月29日 11:45

什么叫“总体结构不变”

就是层级结构还是跟原来的一样

tablecell 回复

把信息抓完之后,用 erb 或 nokogiri 生成都可以吧

require 'rexml/document'
require 'rexml/streamlistener'
require 'pp'

CPU = Struct.new :name, :frequncy
GPU = Struct.new :name, :benmark

class Listener
  include REXML::StreamListener

  attr_reader :xml, :items

  def initialize
    @xml =[]
    @items = []
  end

  def tag_start name, attrs
    xml << name
  end

  def text t
    case xml 
    when ["computer", "cpu", "item", "name"]
      items << CPU.new(t) if t =~ /amd/i
    when ["computer", "cpu", "item", "frequncy"]
      items.last.frequncy = t if not items.empty? and CPU === items.last and not items.last.frequncy
    when ["computer", "gpu", "item", "name"]
      items << GPU.new(t) if t =~ /radeon/i
    when ["computer", "gpu", "item", "benmark"]
      items.last.benmark = t if not items.empty? and GPU === items.last and not items.last.benmark
    end
  end

  def tag_end name
    xml.pop
  end
end

listener = Listener.new

parser = REXML::Parsers::StreamParser.new(File.new("/tmp/t.xml"), listener)

parser.parse

pp listener.items
需要 登录 后方可回复, 如果你还没有账号请 注册新账号