Del*_*man 8 ruby-on-rails docx rubyzip nokogiri
我正在使用rubyzip和nokogiri的组合来编辑.docx文件.我正在使用rubyzip来解压缩.docx文件,然后使用nokogiri来解析和更改word/document.xml文件的正文,但是我最后关闭rubyzip它会破坏文件而我无法打开它或者修理它.我在桌面上解压缩.docx文件并检查word/document.xml文件,并将内容更新为我更改为的内容,但所有其他文件都搞砸了.有人可以帮我解决这个问题吗?这是我的代码:
require 'rubygems'
require 'zip/zip'
require 'nokogiri'
zip = Zip::ZipFile.open("test.docx")
doc = zip.find_entry("word/document.xml")
xml = Nokogiri::XML.parse(doc.get_input_stream)
wt = xml.root.xpath("//w:t", {"w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}).first
wt.content = "New Text"
zip.get_output_stream("word/document.xml") {|f| f << xml.to_s}
zip.close
Run Code Online (Sandbox Code Playgroud)
Eri*_*son 12
昨晚我遇到了与rubyzip相同的腐败问题.我通过将所有内容复制到新的zip文件来解决它,根据需要替换文件.
这是我的工作概念证明:
#!/usr/bin/env ruby
require 'rubygems'
require 'zip/zip' # rubyzip gem
require 'nokogiri'
class WordXmlFile
def self.open(path, &block)
self.new(path, &block)
end
def initialize(path, &block)
@replace = {}
if block_given?
@zip = Zip::ZipFile.open(path)
yield(self)
@zip.close
else
@zip = Zip::ZipFile.open(path)
end
end
def merge(rec)
xml = @zip.read("word/document.xml")
doc = Nokogiri::XML(xml) {|x| x.noent}
(doc/"//w:fldSimple").each do |field|
if field.attributes['instr'].value =~ /MERGEFIELD (\S+)/
text_node = (field/".//w:t").first
if text_node
text_node.inner_html = rec[$1].to_s
else
puts "No text node for #{$1}"
end
end
end
@replace["word/document.xml"] = doc.serialize :save_with => 0
end
def save(path)
Zip::ZipFile.open(path, Zip::ZipFile::CREATE) do |out|
@zip.each do |entry|
out.get_output_stream(entry.name) do |o|
if @replace[entry.name]
o.write(@replace[entry.name])
else
o.write(@zip.read(entry.name))
end
end
end
end
@zip.close
end
end
if __FILE__ == $0
file = ARGV[0]
out_file = ARGV[1] || file.sub(/\.docx/, ' Merged.docx')
w = WordXmlFile.open(file)
w.force_settings
w.merge('First_Name' => 'Eric', 'Last_Name' => 'Mason')
w.save(out_file)
end
Run Code Online (Sandbox Code Playgroud)
小智 1
我偶然发现了这篇文章,对 ruby 或 nokogiri 一无所知,但是......
您似乎错误地重新压缩了新内容。我不了解 rubyzip,但您需要一种方法来告诉它更新条目 word/document.xml,然后重新保存/重新压缩文件。
看起来您只是用新数据覆盖该条目,当然,新数据的大小会有所不同,并且完全搞砸了 zip 文件的其余部分。
我在这篇文章中给出了一个 excel 的例子解析文本文件并创建一个 excel 报告
即使我使用不同的zip库和VB,这也可能有用(我仍然在做你想做的事情,我的代码大约是一半)
这是适用的部分
Using z As ZipFile = ZipFile.Read(xlStream.BaseStream)
'Grab Sheet 1 out of the file parts and read it into a string.
Dim myEntry As ZipEntry = z("xl/worksheets/sheet1.xml")
Dim msSheet1 As New MemoryStream
myEntry.Extract(msSheet1)
msSheet1.Position = 0
Dim sr As New StreamReader(msSheet1)
Dim strXMLData As String = sr.ReadToEnd
'Grab the data in the empty sheet and swap out the data that I want
Dim str2 As XElement = CreateSheetData(tbl)
Dim strReplace As String = strXMLData.Replace("<sheetData/>", str2.ToString)
z.UpdateEntry("xl/worksheets/sheet1.xml", strReplace)
'This just rezips the file with the new data it doesnt save to disk
z.Save(fiRet.FullName)
End Using
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4600 次 |
| 最近记录: |