Ruby XML, XSLT 和 XPath 教程
在 Ruby 中,处理 XML(Extensible Markup Language)、XSLT(Extensible Stylesheet Language Transformations) 和 XPath(XML Path Language) 是常见的任务,特别是在需要解析、转换或查询结构化数据的场景。Ruby 提供了多种库(如 Nokogiri
)来处理这些技术。本教程将重点讲解如何使用 Ruby 处理 XML、XSLT 和 XPath,涵盖核心概念、安装、基本操作、示例代码及注意事项,力求简洁清晰。
1. 概述
- XML:一种标记语言,用于存储和传输结构化数据。
- XPath:一种查询语言,用于在 XML 文档中定位节点或提取数据。
- XSLT:一种转换语言,用于将 XML 文档转换为其他格式(如 HTML、XML)。
- Ruby 工具:
Nokogiri
是最流行的 Ruby 库,支持 XML 解析、XPath 查询和 XSLT 转换。
2. 安装 Nokogiri
Nokogiri
是 Ruby 中处理 XML 和 HTML 的首选库,支持 XPath 和 XSLT。
先决条件
- 安装开发依赖库:
- Ubuntu:
bash sudo apt-get install libxml2-dev libxslt1-dev
- macOS:
bash brew install libxml2 libxslt
- Windows:通常无需额外安装,gem 会自动处理。
安装 Nokogiri
gem install nokogiri
验证:
require 'nokogiri'
puts Nokogiri::VERSION # 输出:1.15.4(示例版本)
3. XML 解析与操作
Nokogiri
提供了简单的方法来解析和操作 XML 文档。
解析 XML
require 'nokogiri'
# 示例 XML
xml = <<~XML
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="1">
<name>Alice</name>
<age>30</age>
</employee>
<employee id="2">
<name>Bob</name>
<age>25</age>
</employee>
</employees>
XML
# 解析 XML
doc = Nokogiri::XML(xml)
puts doc.to_xml # 输出格式化的 XML
说明:
Nokogiri::XML(string)
:解析 XML 字符串。to_xml
:将文档转换回 XML 字符串。
创建 XML
使用 Nokogiri::XML::Builder
创建 XML。
require 'nokogiri'
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
xml.employees do
xml.employee(id: 1) do
xml.name "Alice"
xml.age 30
end
xml.employee(id: 2) do
xml.name "Bob"
xml.age 25
end
end
end
puts builder.to_xml
输出:
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="1">
<name>Alice</name>
<age>30</age>
</employee>
<employee id="2">
<name>Bob</name>
<age>25</age>
</employee>
</employees>
修改 XML
# 修改节点内容
doc.xpath("//employee[@id='1']/name").first.content = "Alicia"
# 添加新节点
employee = doc.xpath("//employee[@id='2']").first
employee.add_child("<role>Developer</role>")
puts doc.to_xml
输出(部分):
<employee id="1">
<name>Alicia</name>
<age>30</age>
</employee>
<employee id="2">
<name>Bob</name>
<age>25</age>
<role>Developer</role>
</employee>
4. XPath 查询
XPath 用于在 XML 文档中定位节点或提取数据。Nokogiri
支持完整的 XPath 语法。
基本 XPath 查询
require 'nokogiri'
xml = <<~XML
<employees>
<employee id="1">
<name>Alice</name>
<age>30</age>
</employee>
<employee id="2">
<name>Bob</name>
<age>25</age>
</employee>
</employees>
XML
doc = Nokogiri::XML(xml)
# 查询所有员工姓名
names = doc.xpath("//employee/name")
names.each { |name| puts name.text } # 输出:Alice, Bob
# 查询 id=1 的员工
employee = doc.xpath("//employee[@id='1']")
puts employee.first['id'] # 输出:1
# 查询年龄大于 25 的员工姓名
older_names = doc.xpath("//employee[age > 25]/name")
puts older_names.first.text # 输出:Alice
常见 XPath 语法:
//node
:选择所有指定节点。/node
:选择直接子节点。@attribute
:选择属性。[condition]
:筛选条件(如[age > 25]
)。text()
:获取节点文本内容。
使用 CSS 选择器(替代 XPath)
Nokogiri
也支持 CSS 选择器,语法更简洁:
names = doc.css("employee name")
puts names.map(&:text) # 输出:["Alice", "Bob"]
5. XSLT 转换
XSLT 用于将 XML 转换为其他格式(如 HTML)。Nokogiri
支持通过 xslt
方法应用 XSLT 样式表。
XSLT 示例
XML 文件(employees.xml
):
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="1">
<name>Alice</name>
<age>30</age>
</employee>
<employee id="2">
<name>Bob</name>
<age>25</age>
</employee>
</employees>
XSLT 样式表(style.xslt
):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Employee List</h1>
<table border="1">
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
</tr>
<xsl:for-each select="employees/employee">
<tr>
<td><xsl:value-of select="@id"/></td>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="age"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Ruby 代码:
require 'nokogiri'
# 加载 XML 和 XSLT
xml = Nokogiri::XML(File.read('employees.xml'))
xslt = Nokogiri::XSLT(File.read('style.xslt'))
# 应用转换
result = xslt.transform(xml)
puts result.to_s
输出(HTML):
<html>
<body>
<h1>Employee List</h1>
<table border="1">
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>1</td>
<td>Alice</td>
<td>30</td>
</tr>
<tr>
<td>2</td>
<td>Bob</td>
<td>25</td>
</tr>
</table>
</body>
</html>
说明:
Nokogiri::XSLT
:加载 XSLT 样式表。transform
:应用 XSLT 转换,返回结果文档。
6. 异常处理
处理 XML、XPath 或 XSLT 时可能遇到解析错误或文件缺失。
require 'nokogiri'
begin
xml = Nokogiri::XML("<invalid>xml") # 无效 XML
rescue Nokogiri::XML::SyntaxError => e
puts "XML 解析错误: #{e.message}"
end
begin
xslt = Nokogiri::XSLT(File.read('nonexistent.xslt'))
rescue Errno::ENOENT
puts "XSLT 文件不存在"
end
常见异常:
Nokogiri::XML::SyntaxError
:XML 格式错误。Errno::ENOENT
:文件不存在。Nokogiri::XSLT::ParseError
:XSLT 样式表错误。
7. 注意事项
- 性能:
- 大型 XML 文件使用流式解析(
Nokogiri::XML::Reader
):ruby Nokogiri::XML::Reader(File.open('large.xml')).each do |node| puts node.name if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT end
- 缓存 XSLT 样式表对象,避免重复解析。
- 编码:确保 XML 和 XSLT 文件使用一致的编码(如 UTF-8)。
- 安全性:
- 验证外部 XML 输入,防止 XML 注入(如实体扩展攻击)。
- 使用
Nokogiri::XML(..., Nokogiri::XML::ParseOptions::NOENT)
禁用外部实体。 - XPath vs CSS:CSS 选择器更直观,适合简单查询;XPath 更强大,适合复杂定位。
- 调试:使用
to_xml
或to_s
检查文档结构。 - 依赖:确保
libxml2
和libxslt
正确安装,否则Nokogiri
可能报错。
8. 综合示例
以下示例解析 XML,使用 XPath 提取数据,并通过 XSLT 转换为 HTML。
require 'nokogiri'
# 示例 XML
xml = <<~XML
<employees>
<employee id="1">
<name>Alice</name>
<age>30</age>
</employee>
<employee id="2">
<name>Bob</name>
<age>25</age>
</employee>
</employees>
XML
# 示例 XSLT
xslt = <<~XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Employees</h1>
<ul>
<xsl:for-each select="employees/employee">
<li><xsl:value-of select="name"/> (Age: <xsl:value-of select="age"/>)</li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
XSLT
begin
# 解析 XML
doc = Nokogiri::XML(xml)
# XPath 查询
names = doc.xpath("//employee[age > 25]/name").map(&:text)
puts "年龄大于 25 的员工: #{names.join(', ')}" # 输出:Alice
# XSLT 转换
xslt_doc = Nokogiri::XSLT(xslt)
result = xslt_doc.transform(doc)
puts result.to_s
rescue Nokogiri::XML::SyntaxError, Nokogiri::XSLT::ParseError => e
puts "解析错误: #{e.message}"
end
输出:
年龄大于 25 的员工: Alice
<html>
<body>
<h1>Employees</h1>
<ul>
<li>Alice (Age: 30)</li>
<li>Bob (Age: 25)</li>
</ul>
</body>
</html>
9. 总结
Ruby 通过 Nokogiri
提供强大的 XML、XPath 和 XSLT 支持:
- XML:使用
Nokogiri::XML
解析和修改,Nokogiri::XML::Builder
创建。 - XPath:通过
xpath
方法查询节点,支持复杂条件。 - XSLT:通过
Nokogiri::XSLT
转换 XML 为 HTML 或其他格式。
注意编码一致性、性能优化(如流式解析)和安全性(如防止 XML 注入)。Nokogiri
是 Ruby 中处理 XML 的首选库,适合各种复杂场景。
如果你需要更复杂的示例(如大型 XML 处理、XSLT 参数传递)或有其他问题,请告诉我!