2010-10-07 68 views
8

我正在使用rubyzip和nokogiri的組合來編輯.docx文件。我正在使用rubyzip解壓縮.docx文件,然後使用nokogiri解析並更改word/document.xml文件的正文,但有時候我關閉了rubyzip,最終破壞了文件,我無法打開它或修理它。我將桌面上的.docx文件解壓縮,並檢查word/document.xml文件,內容更新爲我更改的內容,但所有其他文件都混亂了。有人可以幫我解決這個問題嗎?這裏是我的代碼:如何使用nokogiri和rubyzip編輯docx

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 
+0

你好Delvin,我得到了同樣的問題,但我無法解決它,埃裏克建議。我該如何解決這個問題?謝謝 – Rubyist 2012-01-31 05:18:03

回答

1

我迷迷糊糊翻過後一竅不通紅寶石或引入nokogiri但是......

看起來你是不正確reziping新的內容。 我不知道rubyzip,但你需要一種方式來告訴它更新詞條/ document.xml ,然後重新保存/重新壓縮文件。

它看起來像你剛剛用新數據覆蓋條目,當然這將是一個不同的大小,並完全搞砸了其餘的zip文件。

我給在這個崗位Parse text file and create an excel report

這可能是即使我使用的是不同的拉鍊庫和VB(IM仍然在做什麼你正在嘗試做使用Excel的一個例子,我的代碼是關於按下一半)

這裏是適用

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 
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 
+0

'w.force_settings'這行是做什麼/引用的? – Simmo 2013-10-28 11:15:35

+1

不知道如何排除這種方法,但它是這樣的:https://gist.github.com/ericmason/7200421 另外這裏是我有最新副本的完整文件: https://gist.github。 COM/ericmason/7200448 – 2013-10-28 16:50:26