docxedit 0.0.2 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,5 @@
1
1
  module DocxEdit
2
2
  class ContentBlock
3
-
4
3
  attr_accessor :content
5
4
 
6
5
  def initialize(xml, content)
@@ -9,6 +8,10 @@ module DocxEdit
9
8
  @content = content
10
9
  end
11
10
 
11
+ def clone
12
+ result = ContentBlock.new(rclone_xml(@xml), @content_key)
13
+ end
14
+
12
15
  def xml
13
16
  unless(@content_key == @content)
14
17
  @node = REXML::XPath.first(@xml, "//*[text()='#{@content_key}']]")
@@ -17,5 +20,17 @@ module DocxEdit
17
20
  end
18
21
  return @xml
19
22
  end
23
+
24
+ private
25
+
26
+ def rclone_xml(node)
27
+ new_node = node.clone
28
+ unless node.node_type == :text
29
+ node.children.each do |c|
30
+ new_node << rclone_xml(c)
31
+ end
32
+ end
33
+ return new_node
34
+ end
20
35
  end
21
36
  end
@@ -1,19 +1,26 @@
1
1
  require 'zip/zip'
2
2
  require "rexml/document"
3
+ require 'tempfile'
3
4
  require_relative 'content_block'
4
5
 
5
6
  module DocxEdit
6
7
  class Docx
7
- attr_reader :zip_file, :xml_document
8
+ attr_reader :zip_file, :xml_document, :xml_headers, :xml_footers
8
9
 
9
10
  def initialize(path)
10
11
  @zip_file = Zip::ZipFile.new(path)
11
- @xml_document = REXML::Document.new(read_content)
12
+ bind_contents
13
+ end
14
+
15
+ def files
16
+ return @xml_headers + @xml_footers + [@xml_document]
12
17
  end
13
18
 
14
19
  def contains?(text)
15
- REXML::XPath.each @xml_document, XPATH_ALL_TEXT_NODE do |n|
16
- return true if n.text =~ text
20
+ files.each do |f|
21
+ REXML::XPath.each f, XPATH_ALL_TEXT_NODE do |n|
22
+ return true if n.text =~ text
23
+ end
17
24
  end
18
25
  return false
19
26
  end
@@ -24,14 +31,18 @@ module DocxEdit
24
31
  end
25
32
 
26
33
  def replace(reg_to_match, replacement)
27
- REXML::XPath.each @xml_document, XPATH_ALL_TEXT_NODE do |n|
28
- n.text = n.text.gsub(reg_to_match, replacement)
34
+ files.each do |f|
35
+ REXML::XPath.each f, XPATH_ALL_TEXT_NODE do |n|
36
+ n.text = n.text.gsub(reg_to_match, replacement)
37
+ end
29
38
  end
30
39
  end
31
40
 
32
41
  def find_block_with_content(exact_content_string)
33
- node = REXML::XPath.first(@xml_document, "//w:p[descendant-or-self::*[text()='#{exact_content_string}']]")
34
- return ContentBlock.new(node, exact_content_string)
42
+ files.each do
43
+ node = REXML::XPath.first(@xml_document, "//w:p[descendant-or-self::*[text()='#{exact_content_string}']]")
44
+ return ContentBlock.new(node, exact_content_string) unless node.nil?
45
+ end
35
46
  end
36
47
 
37
48
  # insert the xml of a content block :before or :after the anchor_block
@@ -54,17 +65,64 @@ module DocxEdit
54
65
  DOCUMENT_FILE_PATH = 'word/document.xml'
55
66
  XPATH_ALL_TEXT_NODE = "//*[text()]"
56
67
 
57
- def read_content()
58
- return text = @zip_file.read(DOCUMENT_FILE_PATH)
68
+ def bind_contents
69
+ @xml_document = REXML::Document.new(@zip_file.read(DOCUMENT_FILE_PATH))
70
+ @xml_headers = []
71
+ @xml_footers = []
72
+ REXML::Document.new(@zip_file.read(DOCUMENT_FILE_PATH))
73
+
74
+ idx = 1
75
+ src = read_or_nil("word/header#{idx}.xml")
76
+ while(!src.nil?) do
77
+ @xml_headers << REXML::Document.new(src)
78
+ idx = idx + 1
79
+ src = read_or_nil("word/header#{idx}.xml")
80
+ end
81
+
82
+ idx = 1
83
+ src = read_or_nil("word/footer#{idx}.xml")
84
+ while(!src.nil?) do
85
+ @xml_headers << REXML::Document.new(src)
86
+ idx = idx + 1
87
+ src = read_or_nil("word/footer#{idx}.xml")
88
+ end
89
+ end
90
+
91
+
92
+ def read_or_nil(name)
93
+ return @zip_file.read(name) rescue return nil
94
+ end
95
+
96
+ def write_entry(zip_output_stream, entry_name, xml_doc)
97
+ zip_output_stream.put_next_entry(entry_name)
98
+ output = ""
99
+ xml_doc.write(output, 0)
100
+ zip_output_stream.print output
59
101
  end
60
102
 
61
103
  def write_content()
62
- @zip_file.get_output_stream(DOCUMENT_FILE_PATH) do |input|
63
- output = ""
64
- @xml_document.write(output, 0)
65
- input.write output
104
+ temp_file = Tempfile.new('docxedit-')
105
+ Zip::ZipOutputStream.open(temp_file.path) do |zos|
106
+ @zip_file.entries.each do |e|
107
+ unless e.name == DOCUMENT_FILE_PATH || e.name =~ /word\/(header|footer)[0-9]+\.xml/
108
+ zos.put_next_entry(e.name)
109
+ zos.print e.get_input_stream.read
110
+ end
111
+ end
112
+
113
+ write_entry(zos, DOCUMENT_FILE_PATH, @xml_document)
114
+ (0 .. @xml_headers.size - 1).each do |idx|
115
+ write_entry zos, "word/header#{idx + 1}.xml", @xml_headers[idx]
116
+ end
117
+ (0 .. @xml_footers.size - 1).each do |idx|
118
+ write_entry zos, "word/footer#{idx + 1}.xml", @xml_footers[idx]
119
+ end
66
120
  end
67
- @zip_file.commit
121
+
122
+ path = @zip_file.name
123
+ FileUtils.rm(path)
124
+ FileUtils.mv(temp_file.path, path)
125
+ @zip_file = Zip::ZipFile.new(path)
68
126
  end
69
127
  end
70
128
  end
@@ -1,3 +1,3 @@
1
1
  module DocxEdit
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.5"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docxedit
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Olivier Amblet
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-10 00:00:00 +01:00
18
+ date: 2011-02-14 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: rspec
22
+ name: rubyzip
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
@@ -30,8 +30,22 @@ dependencies:
30
30
  segments:
31
31
  - 0
32
32
  version: "0"
33
- type: :development
33
+ type: :runtime
34
34
  version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
35
49
  description: minimal .docx file editor.
36
50
  email: olivier@amblet.net
37
51
  executables: []