Ruby 如何解析XML并根据节点内容执行操作?

Ruby 如何解析XML并根据节点内容执行操作?,ruby,xml,nokogiri,Ruby,Xml,Nokogiri,我有一个XML文件,它将输出一个字符串: <mystring> <manipulate type="caps"> <string>Hello There!</string> <repeat times="4"> <string> FooBar</string> </repeat> </manipulate&g

我有一个XML文件,它将输出一个字符串:

<mystring>
    <manipulate type="caps">
        <string>Hello There!</string>
        <repeat times="4">
            <string> FooBar</string>
        </repeat>
    </manipulate>
    <string>!</string>
</mystring>
我想解释XML节点并执行某些操作或输出某些字符串。我想要一个干净的方法来做这件事。这只是一个简化的版本,会有其他节点具有更复杂的功能,但我需要一些入门帮助

我试图用Nokogiri来做,但我有点挣扎

f = File.open("file.xml")
doc = Nokogiri::XML(f)
f.close

result = []

doc.root.children.each do |node|
  if node.name == "string"
    result.push(node.inner_text)
    repeat = node.children[0]
    times = repeat["times"]
    for i in 1..times do
      result.append(repeat.inner_text)
    end
  end
  ...
end

" ".join(result)

差不多吧。老实说,我自己还没有使用NokGoiRi,但希望这是有帮助的。

< P>我的尝试,使用递归和映射,我认为函数编程优雅:

需要“nokogiri”

def build_string_from_xml(nodes)
  nodes.map { |node|
    inner_str = build_string_from_xml(node.xpath("./*"))
    case node.name
    when "string"
      node.content
    when "repeat"
      if node[:type] == "numbered"
        1.upto(node[:times].to_i).map { |i|
          inner_str + i.to_s
        }.join
      else
        inner_str * node[:times].to_i
      end
    when "manipulate"
      if node[:type] == "caps"
        inner_str.upcase
      else
        raise ArgumentError, "Don't know that manipulation type: %s" % node[:type]
      end
    else
      raise ArgumentError, "Don't know that tag: %s" % node.name
    end
  }.join
end

doc = Nokogiri::XML.parse(<<-XML)
<mystring>
  <manipulate type="caps">
    <string>Hello There!</string>
    <repeat times="4">
      <string> FooBar</string>
    </repeat>
    <string>!</string>
  </manipulate>

  <repeat times="3" type="numbered">
    <string> FooBar</string>
  </repeat>
</mystring>
XML

p build_string_from_xml(doc.xpath("//mystring/*"))

你在使用Nnokogiri时遇到了什么特别的问题?我对Nokogiri没有任何问题,我可以查找节点、它们的值和属性,但我真的不知道如何将其应用于我的情况。这更像是一个红宝石问题。嗨,Niklas。谢谢你,这正是我想要的。只是想知道如何使用代码根据重复的内容为每个重复的字符串指定一个数字。输出字符串如下所示。。。你好!FooBar1 FooBar2 FooBar3 FooBar4!我为该任务添加了一个替代实现,并在原始实现中用map替换了inject,因为它看起来更干净一些。请不要在将来增加有关该问题的信息,这违反了StackOverflow原则。好的。谢谢我还有一个问题与此非常相关,我是否要问一个新问题?nodes.map{| result,node |应该是nodes.map{| node |。您正在传入一个节点集,它的作用类似于一个节点数组。@管理员:您是对的,当我从“注入”更改为“映射”时发生了这种情况。尼克:这是我的最后一次编辑,如果不能单独从这里开始而不是使用“文件”,请打开一个新问题。打开然后关闭文件,使用File.read或将一个块传递给File.open,关闭它自动地。
def build_string_from_xml(nodes)
  nodes.map { |node|
    inner_str = build_string_from_xml(node.xpath("./*"))
    case node.name
    when "string"
      node.content
    when "repeat"
      if node[:type] == "numbered"
        1.upto(node[:times].to_i).map { |i|
          inner_str + i.to_s
        }.join
      else
        inner_str * node[:times].to_i
      end
    when "manipulate"
      if node[:type] == "caps"
        inner_str.upcase
      else
        raise ArgumentError, "Don't know that manipulation type: %s" % node[:type]
      end
    else
      raise ArgumentError, "Don't know that tag: %s" % node.name
    end
  }.join
end

doc = Nokogiri::XML.parse(<<-XML)
<mystring>
  <manipulate type="caps">
    <string>Hello There!</string>
    <repeat times="4">
      <string> FooBar</string>
    </repeat>
    <string>!</string>
  </manipulate>

  <repeat times="3" type="numbered">
    <string> FooBar</string>
  </repeat>
</mystring>
XML

p build_string_from_xml(doc.xpath("//mystring/*"))