2010-10-07 5 views
8

Ich verwende eine Kombination aus Rubyzip und Nokogiri, um eine .docx-Datei zu bearbeiten. Ich benutze Rubyzip, um die .docx Datei zu entpacken und nokogiri zu verwenden, um den Text der Datei word/document.xml zu analysieren und zu ändern, aber immer wenn ich rubyzip schließe, korrumpiert er die Datei und ich kann sie nicht öffnen oder repariere es. Ich entzippe die .docx-Datei auf dem Desktop und überprüfe die Datei "word/document.xml" und der Inhalt wird auf das aktualisiert, was ich geändert habe, aber alle anderen Dateien sind durcheinander. Könnte mir jemand bei diesem Problem helfen? Hier ist mein Code:So bearbeiten Sie docx mit nokogiri und rubyzip

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

Hallo Delvin, ich habe das gleiche Problem, aber ich kann es nicht lösen, wie Eric vorgeschlagen hat. Wie kann ich dieses Problem beheben? Danke – Rubyist

Antwort

1

ich auf der anderen Post gestolpert und wissen nichts über Rubin oder nokogiri aber ...

Es sieht aus wie Sie den neuen Inhalt falsch sind reziping. Ich weiß nicht, über Rubyzip, aber Sie müssen eine Möglichkeit, um es zu sagen, um das Eintragswort/document.xml zu aktualisieren und dann erneut speichern/erneut die Datei.

Es sieht so aus, als ob Sie nur den Eintrag mit neuen Daten überschreiben, die natürlich eine andere Größe haben und den Rest der Zip-Datei total vermasseln werden.

Ich gebe ein Beispiel für excel in diesem Beitrag Parse text file and create an excel report

, die auch von Nutzen sein können, obwohl ich eine andere ZIP-Bibliothek bin mit und VB (Im noch genau das, was Sie versuchen, mein Code zu tun, ist über auf halbem Weg nach unten)

hier ist der Teil,

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

ich mit rubyzip gestern Abend lief in das gleiche Korruption Problem gilt. Ich löste es, indem ich alles in eine neue Zip-Datei kopierte und die Dateien nach Bedarf ersetzte.

Hier ist meine Arbeits Proof of Concept:

#!/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

Was bedeutet die Zeile 'w.force_settings'? – Simmo

+1

Nicht sicher, wie diese Methode ausgelassen wurde, aber es ist das: https://gist.github.com/ericmaon/7200421 Auch hier ist die vollständige Datei von der neuesten Kopie, die ich habe: https: //gist.github. com/ericmason/7200448 –

Verwandte Themen