如何使用Ruby / Nokogiri连接两个XML标签?

时间:2012-02-10 19:50:57

标签: ruby xml parsing

我使用Ruby来检索具有以下格式的XML文档:

<project>
  <users>
   <person>
     <name>LUIS</name>
   </person>
   <person>
     <name>JOHN</name>
   </person>
  </users>
</project>

我想知道如何产生以下结果,标签连接在一起:

<project>
    <users>
      <person>
        <name>LUIS JOHN</name>
      </person>
    </users>
</project>

以下是我正在使用的代码:

file = File.new( "proyectos.xml" )
doc3 = Nokogiri::XML(file)
a=0

@participa = doc3.search("person")
@participa.each do |i|

     @par = @participa.search("name").map { |node| node.children.text }

     @par.each do |i|
         puts @par[a]
         puts '--'
         a = a + 1
    end 

end

1 个答案:

答案 0 :(得分:1)

不是提供代码,而是如何捕鱼:

要将您的XML解析为Nokogiri,我强烈建议:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<project>
  <users>
   <person>
     <name>LUIS</name>
   </person>
   <person>
     <name>JOHN</name>
   </person>
  </users>
</project>
EOT

它为您提供了一个doc变量,它是一个Nokogiri :: XML :: Document的DOM。从中您可以搜索匹配的节点或特定节点。 search允许您传递XPath或CSS访问器以找到您要查找的内容。我推荐CSS用于大多数事情,因为它更具可读性,但是XPath有一些很好的工具可以深入研究XML的结构,因此我的代码中经常会出现这两种情况。

因此,doc.at('users')是查找第一个users节点的CSS访问器。 doc.search('person')会将与person标记匹配的所有节点作为NodeSet返回,这基本上是一个可以枚举或循环的数组。

Nokogiri有一个节点的text方法,它允许您获取该节点的文本内容,包括节点之间的所有回车,这些节点通常在XML向下流动文档时被视为格式化。当您拥有节点的文本时,您可以应用常规的Ruby字符串处理命令,例如stripsquishchomp等,以便将文本按到更有用的位置格式。

Nokogiri还有一个children=方法,可让您重新定义节点的子节点。您可以将您创建的节点,NodeSet,甚至您想要呈现的文本传递到XML中。

在一个快速实验中,我的代码基本上可以完成四行所需的代码。但是,在分享我写的内容之前,我想看看你的作品。

最后,puts doc.to_xml可让您轻松查看对文档的更改是否成功。


我是这样做的:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<project>
  <users>
   <person>
     <name>LUIS</name>
   </person>
   <person>
     <name>JOHN</name>
   </person>
  </users>
</project>
EOT

现在将XML解析为DOM。搜索users标记,然后找到嵌入的name标记并从中提取文本。将结果加入单个以空格分隔的字符串中。然后将users标记的子项替换为所需的结果:

doc.search('users').each do |users|
  user_names = users.search('name').map(&:text).join(' ')
  users.children = "<person><name>#{ user_names }</name></person>"
end

如果您输出结果XML,您将获得:

puts doc.to_xml

<?xml version="1.0"?>
<project>
  <users><person><name>LUIS JOHN</name></person></users>
</project>