Ruby Nokogiri怎么构建XML文档

Nokogiri::XML::Builder.new 是构建 XML 的最可控起点,需注意命名空间声明、属性哈希必须首参、UTF-8 编码显式指定,避免动态追加节点和错误解析方式。

ruby nokogiri怎么构建xml文档

Nokogiri::XML::Builder 创建空文档再填充

直接调用 Nokogiri::XML::Builder.new 是最可控的起点,它默认生成带 XML 声明的空文档,且节点自动闭合逻辑清晰。别用 Nokogiri::XML字符串解析方式来“构建”,那是为解析设计的,强行拼接容易漏转义或结构错乱。

常见错误是传入空字符串或 nil 初始化 builder,导致后续 doc 属性不可用:

Nokogiri::XML::Builder.new { |xml| xml.root { xml.child "text" } }.doc
# ✅ 正确:闭包内定义结构,返回完整文档对象

注意 builder 默认不加换行缩进,如需可手动插入 /n 或用 to_xml(indent: 2) 输出时格式化。

嵌套标签与属性必须用哈希传参

Nokogiri::XML::Builder 的 DSL 要求属性必须作为第一个参数以哈希形式传入,内容(文本或子块)在后。顺序错了会把属性当文本、或抛 ArgumentError

  • xml.tag({ id: "1" }, "value")
  • xml.tag("value", { id: "1" }) ❌ —— 这会把 “value” 当作属性哈希的 key
  • xml.tag(id: "1") { "value" } ✅ —— 块内写文本也合法

特殊字符如 & 会被自动转义,无需手动调 CGI.escape;但 CDATA 需显式调用 xml.cdata 方法。

处理命名空间和前缀要提前声明

如果目标 XML 含命名空间(如 xmlns:ns="http://example.com"),不能靠后期追加属性。必须在根节点初始化时用 xmlns 键声明,并在子节点中用符号前缀引用:

FastGPT

FastGPT

FastGPT 是一个基于 LLM 大语言模型的知识库问答系统

下载

Nokogiri::XML::Builder.new do |xml|
  xml.root("xmlns:ns" => "http://example.com") do
    xml["ns"].item("NS content")
  end
end.doc

没声明就直接写 xml.ns:item 会报 NoMethodError;用字符串前缀如 xml["ns"].item 才是正确语法。多个命名空间可并列传入哈希,但冲突前缀会导致覆盖。

中文或 UTF-8 内容要确保 Builder 实例编码一致

默认 builder 生成文档是 UTF-8 编码,但若 Ruby 源文件本身不是 UTF-8(比如系统 locale 是 GBK),中文字符串可能被错误解释为 ASCII-8BIT,导致输出乱码或 Encoding::CompatibilityError

安全做法是显式指定编码:

Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
  xml.root { xml.text "你好" }
end.doc.to_xml

另外,避免用 doc.root.add_child 动态追加含中文的 Nokogiri::XML::Text 节点——它不会自动继承父节点编码,容易出错。所有内容尽量在 builder 闭包内一次性定义。

命名空间声明、属性传参顺序、编码一致性这三点,实际项目里最容易反复踩坑。

https://www.php.cn/faq/1972062.html

发表回复

Your email address will not be published. Required fields are marked *