我想使用Builder基于 ActiveRecord 模型表构造一组 XML 文件。我有近一百万行,因此我需要使用 find_each(batch_size: 5000)
迭代记录并为每批记录编写一个 XML 文件,直到记录耗尽。类似于以下内容:
filecount = 1
count = 0
xml = ""
Person.find_each(batch_size: 5000) do |person|
xml += person.to_xml # pretend .to_xml() exists
count += 1
if count == MAX_PER_FILE
File.open("#{filecount}.xml", 'w') {|f| f.write(xml) }
xml = ""
filecount += 1
count = 0
end
end
这不适用于 Builder 的界面,因为它希望在 block 中工作,如下所示:
xml = builder.person { |p| p.name("Jim") }
一旦 block 结束,Builder 就会关闭其当前节;你不能保留对 p 的引用并在 block 之外使用它(我尝试过)。基本上,Builder 希望“拥有”迭代。
因此,为了使构建器能够使用此功能,我必须执行以下操作:
filecount = 0
offset = 0
while offset < Person.count do
count = 0
builder = Builder::XmlMarkup.new(indent: 5)
xml = builder.people do |people|
Person.limit(MAX_PER_FILE).offset(offset).each do |person|
people.person { |p| p.name(person.name) }
count += 1
end
end
File.open("#output@file_count.xml", 'w') {|f| f.write(xml) }
filecount += 1
offset += count
end
有没有办法在没有 block 语法的情况下使用Builder?有没有办法以编程方式告诉它“关闭当前节”而不是依赖 block ?
最佳答案
我的建议:不要使用构建器。
只要正确转义 xml 实体,XML 就是一种简单的格式。
对数据库检索进行批处理,然后将批处理作为 xml 写入文件句柄。正如您的示例所示,不要通过字符串进行缓冲。只需写入文件句柄即可。让操作系统处理缓冲。文件可以是任意大小,为什么有限制?
另外,不要包括缩进空格,如果有百万行,它们就会加起来。
已添加 在编写 xml 文件时,我还在文件顶部包含 xml 注释:
- 生成 xml 文件的软件名称和版本
- 文件写入的日期/时间戳
- 其他有用的信息。例如,在这种情况下,您可以说该文件是原始数据集的 # x 批处理。
关于 ruby /生成器 API : create XML without using blocks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11193565/