@@ -18,15 +18,24 @@ module Docx
18
18
# puts d.text
19
19
# end
20
20
class Document
21
- attr_reader :xml , :doc , :zip , :styles
21
+
22
+ # A path with * indicates that there are possibly multiple documents
23
+ # matching that glob, eg. word/header1.xml, word/header2.xml
24
+ DOCUMENT_PATHS = {
25
+ doc : "word/document.xml" ,
26
+ styles : "word/styles.xml" ,
27
+ headers : "word/header*.xml" ,
28
+ footers : "word/footer*.xml" ,
29
+ numbering : "word/numbering.xml"
30
+ }
31
+
32
+ attr_reader :xml , :doc , :zip , :styles , :headers , :footers , :numbering
22
33
23
34
def initialize ( path , &block )
24
35
@replace = { }
25
36
@zip = Zip ::File . open ( path )
26
- @document_xml = @zip . read ( 'word/document.xml' )
27
- @doc = Nokogiri ::XML ( @document_xml )
28
- @styles_xml = @zip . read ( 'word/styles.xml' )
29
- @styles = Nokogiri ::XML ( @styles_xml )
37
+ extract_documents
38
+
30
39
if block_given?
31
40
yield self
32
41
@zip . close
@@ -123,13 +132,49 @@ def replace_entry(entry_path, file_contents)
123
132
124
133
private
125
134
135
+ def extract_documents
136
+ DOCUMENT_PATHS . each do |attr_name , path |
137
+ if path . match /\* /
138
+ extract_multiple_documents_from_globbed_path ( attr_name , path )
139
+ else
140
+ extract_single_document_from_path ( attr_name , path )
141
+ end
142
+ end
143
+ end
144
+
145
+ def extract_single_document_from_path ( attr_name , path )
146
+ if @zip . find_entry ( path )
147
+ xml_doc = @zip . read ( path )
148
+ self . instance_variable_set ( :"@#{ attr_name } " , Nokogiri ::XML ( xml_doc ) )
149
+ end
150
+ end
151
+
152
+ def extract_multiple_documents_from_globbed_path ( hash_attr_name , glob_path )
153
+ files = @zip . glob ( glob_path ) . map { |h | h . name }
154
+ filename_and_contents_pairs = files . map do |file |
155
+ simple_file_name = file . sub ( /^word\/ / , "" ) . sub ( /\. xml$/ , "" )
156
+ [ simple_file_name , Nokogiri ::XML ( @zip . read ( file ) ) ]
157
+ end
158
+ hash = Hash [ filename_and_contents_pairs ]
159
+ self . instance_variable_set ( :"@#{ hash_attr_name } " , hash )
160
+ end
161
+
126
162
#--
127
163
# TODO: Flesh this out to be compatible with other files
128
164
# TODO: Method to set flag on files that have been edited, probably by inserting something at the
129
165
# end of methods that make edits?
130
166
#++
131
167
def update
132
- replace_entry "word/document.xml" , doc . serialize ( :save_with => 0 )
168
+ DOCUMENT_PATHS . each do |attr_name , path |
169
+ if path . match /\* /
170
+ self . instance_variable_get ( "@#{ attr_name } " ) . each do |simple_file_name , contents |
171
+ replace_entry ( "word/#{ simple_file_name } .xml" , contents . serialize ( :save_with => 0 ) )
172
+ end
173
+ else
174
+ xml_document = self . instance_variable_get ( "@#{ attr_name } " )
175
+ replace_entry path , xml_document . serialize ( :save_with => 0 ) if xml_document
176
+ end
177
+ end
133
178
end
134
179
135
180
# generate Elements::Containers::Paragraph from paragraph XML node
0 commit comments