在Ruby生态中,Nokogiri是处理XML和HTML文档的主流库,它提供了简洁的API,能够高效完成XML的解析、修改和生成工作。下面我们就一步步学习如何使用Nokogiri操作XML文档。

环境准备
首先需要在项目中安装Nokogiri库,如果你使用Bundler管理依赖,可以在Gemfile中添加如下内容:
# Gemfile gem 'nokogiri'
之后执行bundle install完成安装,也可以直接通过gem命令安装:
gem install nokogiri
解析XML文档
Nokogiri支持从字符串、本地文件、网络地址等多种来源解析XML文档,解析后会生成对应的文档对象,我们可以基于这个对象操作XML内容。
从字符串解析XML
如果XML内容是字符串形式,可以直接使用Nokogiri::XML方法解析:
require 'nokogiri'
# 待解析的XML字符串
xml_str = <?xml version="1.0" encoding="UTF-8"?>
<root>
<user id="1">
<name>张三</name>
<age>25</age>
</user>
<user id="2">
<name>李四</name>
<age>30</age>
</user>
</root>
# 解析XML字符串
doc = Nokogiri::XML(xml_str)
# 检查解析是否有错误
if doc.errors.empty?
puts "XML解析成功"
else
puts "解析错误:#{doc.errors}"
end从文件解析XML
如果XML内容保存在本地文件中,可以使用Nokogiri::XML(File.open("文件路径"))的方式解析:
require 'nokogiri'
# 解析本地test.xml文件
begin
doc = Nokogiri::XML(File.open("test.xml"))
puts "文件解析成功"
rescue Errno::ENOENT
puts "文件不存在"
end查询XML节点
解析完成后,我们可以通过CSS选择器或者XPath语法查询需要的节点,Nokogiri对两种方式都提供了良好的支持。
使用CSS选择器查询所有user节点:
require 'nokogiri'
xml_str = <?xml version="1.0" encoding="UTF-8"?>
<root>
<user id="1">
<name>张三</name>
<age>25</age>
</user>
<user id="2">
<name>李四</name>
<age>30</age>
</user>
</root>
doc = Nokogiri::XML(xml_str)
# 查询所有user节点
users = doc.css("user")
users.each do |user|
# 获取id属性
id = user["id"]
# 获取子节点name的内容
name = user.at_css("name").text
# 获取子节点age的内容
age = user.at_css("age").text
puts "用户ID:#{id},姓名:#{name},年龄:#{age}"
end使用XPath语法查询指定id的用户节点:
require 'nokogiri'
xml_str = <?xml version="1.0" encoding="UTF-8"?>
<root>
<user id="1">
<name>张三</name>
<age>25</age>
</user>
</root>
doc = Nokogiri::XML(xml_str)
# XPath查询id为1的user节点
target_user = doc.xpath("//user[@id='1']").first
if target_user
puts "找到用户:#{target_user.at_xpath("name").text}"
end修改XML节点
我们可以修改已有节点的内容、属性,也可以新增或删除节点:
require 'nokogiri'
xml_str = <?xml version="1.0" encoding="UTF-8"?>
<root>
<user id="1">
<name>张三</name>
<age>25</age>
</user>
</root>
doc = Nokogiri::XML(xml_str)
user = doc.at_css("user")
# 修改age节点的内容
user.at_css("age").content = "26"
# 新增一个email子节点
email_node = Nokogiri::XML::Node.new("email", doc)
email_node.content = "zhangsan@ipipp.com"
user.add_child(email_node)
# 修改user节点的id属性
user["id"] = "100"
puts doc.to_xml生成XML文档
除了解析已有XML,Nokogiri也支持从零开始生成XML文档,我们可以通过构建节点树的方式生成符合要求的XML内容。
基础XML生成
下面的示例生成一个包含用户信息的简单XML文档:
require 'nokogiri'
# 创建XML文档对象
doc = Nokogiri::XML::Document.new
# 添加XML声明
decl = Nokogiri::XML::Node.new("xml-declaration", doc)
decl["version"] = "1.0"
decl["encoding"] = "UTF-8"
doc.add_child(decl)
# 创建根节点root
root = Nokogiri::XML::Node.new("root", doc)
doc.add_child(root)
# 创建第一个user节点
user1 = Nokogiri::XML::Node.new("user", doc)
user1["id"] = "1"
root.add_child(user1)
# 给user1添加子节点
name1 = Nokogiri::XML::Node.new("name", doc)
name1.content = "张三"
user1.add_child(name1)
age1 = Nokogiri::XML::Node.new("age", doc)
age1.content = "25"
user1.add_child(age1)
# 输出生成的XML字符串
puts doc.to_xml使用Builder简化生成流程
Nokogiri内置了Builder类,可以用更简洁的DSL风格生成XML,代码可读性更高:
require 'nokogiri'
# 使用Builder生成XML
xml_content = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
xml.root do
xml.user(id: "1") do
xml.name "张三"
xml.age "25"
end
xml.user(id: "2") do
xml.name "李四"
xml.age "30"
end
end
end.to_xml
puts xml_content注意事项
- 解析XML时如果文档格式不规范,Nokogiri会尝试自动修正,同时可以通过
doc.errors查看解析过程中的错误信息。 - 生成XML时如果需要保留格式缩进,可以在调用
to_xml时传入indent: 2参数,例如doc.to_xml(indent: 2)。 - 操作节点属性时,通过
节点["属性名"]获取或修改属性,不存在的属性返回nil。
通过以上内容,我们已经掌握了Nokogiri解析和生成XML文档的核心方法,在实际开发中可以根据需求选择合适的API完成XML相关的操作。