docx_manipulator 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.rdoc +3 -0
- data/Rakefile +1 -0
- data/docx_manipulator.gemspec +25 -0
- data/lib/docx_manipulator.rb +77 -0
- data/lib/docx_manipulator/version.rb +3 -0
- data/spec/docx_manipulator_spec.rb +100 -0
- data/spec/files/content.txt +1 -0
- data/spec/files/data.xml +25 -0
- data/spec/files/document.xslt +23 -0
- data/spec/files/duck.jpeg +0 -0
- data/spec/files/movies.docx +0 -0
- metadata +105 -0
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm --create ruby-1.9.2-p180@docx_manipulator
|
data/Gemfile
ADDED
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "docx_manipulator/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "docx_manipulator"
|
7
|
+
s.version = DocxManipulator::VERSION
|
8
|
+
s.authors = ["Michael Stämpfli"]
|
9
|
+
s.email = ["michael.staempfli@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Enables the modification of docx files.}
|
12
|
+
s.description = %q{This Gem enables you to modify the contents of docx files.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "docx_manipulator"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
s.add_runtime_dependency "rubyzip"
|
24
|
+
s.add_runtime_dependency "nokogiri"
|
25
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'docx_manipulator/version'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'zip/zip'
|
4
|
+
|
5
|
+
class DocxManipulator
|
6
|
+
|
7
|
+
attr_reader :source, :target, :new_content, :new_relationships
|
8
|
+
|
9
|
+
def initialize(source, target)
|
10
|
+
@source = source
|
11
|
+
@target = target
|
12
|
+
@new_relationships = source_relationships
|
13
|
+
@images = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def source_content
|
17
|
+
content = ''
|
18
|
+
Zip::ZipFile.open(source) do |file|
|
19
|
+
content = file.read('word/document.xml')
|
20
|
+
end
|
21
|
+
content
|
22
|
+
end
|
23
|
+
|
24
|
+
def source_relationships
|
25
|
+
content = ''
|
26
|
+
Zip::ZipFile.open(source) do |file|
|
27
|
+
content = file.read('word/_rels/document.xml.rels')
|
28
|
+
end
|
29
|
+
Nokogiri::XML.parse(content)
|
30
|
+
end
|
31
|
+
|
32
|
+
def content(new_content, options = {})
|
33
|
+
new_content_string = case new_content
|
34
|
+
when File then new_content.read
|
35
|
+
else new_content
|
36
|
+
end
|
37
|
+
if options.include?(:xslt)
|
38
|
+
xslt = Nokogiri::XSLT.parse(options[:xslt])
|
39
|
+
data = Nokogiri::XML.parse(new_content_string)
|
40
|
+
@new_content = xslt.transform(data).to_s
|
41
|
+
else
|
42
|
+
@new_content = new_content_string
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_image(id, path)
|
47
|
+
@images[id] = path
|
48
|
+
image_node = Nokogiri::XML::Node.new('Relationship', new_relationships)
|
49
|
+
image_node['Id'] = id
|
50
|
+
image_node['Type'] = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'
|
51
|
+
image_node['Target'] = "media/#{File.basename(path)}"
|
52
|
+
new_relationships.root << image_node
|
53
|
+
end
|
54
|
+
|
55
|
+
def process
|
56
|
+
Zip::ZipOutputStream.open(target) do |os|
|
57
|
+
Zip::ZipFile.foreach(source) do |entry|
|
58
|
+
os.put_next_entry entry.name
|
59
|
+
if entry.name == 'word/document.xml'
|
60
|
+
os.write @new_content
|
61
|
+
elsif entry.name == 'word/_rels/document.xml.rels'
|
62
|
+
os.write new_relationships.to_s
|
63
|
+
elsif entry.file?
|
64
|
+
os.write entry.get_input_stream.read
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
@images.each do |id, path|
|
69
|
+
os.put_next_entry "word/media/#{File.basename(path)}"
|
70
|
+
File.open(path) do |file|
|
71
|
+
IO.copy_stream file, os
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'docx_manipulator'
|
2
|
+
require 'zip/zip'
|
3
|
+
|
4
|
+
describe DocxManipulator do
|
5
|
+
|
6
|
+
subject { DocxManipulator.new('spec/files/movies.docx', 'spec/files/result.docx') }
|
7
|
+
|
8
|
+
describe "#source_content" do
|
9
|
+
it "returns the content of document.xml" do
|
10
|
+
subject.source_content.should =~ /w:document/
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#content" do
|
15
|
+
let(:xml_string) { <<-EOF
|
16
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
17
|
+
<Movies>
|
18
|
+
<Genre name="Drama">
|
19
|
+
<Movie>
|
20
|
+
<Name>The Departed</Name>
|
21
|
+
<Released>2006</Released>
|
22
|
+
</Movie>
|
23
|
+
<Movie>
|
24
|
+
<Name>The Pursuit of Happyness</Name>
|
25
|
+
<Released>2006</Released>
|
26
|
+
</Movie>
|
27
|
+
</Genre>
|
28
|
+
</Movies>
|
29
|
+
EOF
|
30
|
+
}
|
31
|
+
|
32
|
+
it "transforms the data file with an xslt file" do
|
33
|
+
subject.content File.new('spec/files/data.xml'), :xslt => File.new('spec/files/document.xslt')
|
34
|
+
subject.new_content.should =~ /<w:t>The Departed<\/w:t>/
|
35
|
+
subject.new_content.should =~ /<w:t>The Pursuit of Happyness<\/w:t>/
|
36
|
+
end
|
37
|
+
|
38
|
+
it "transforms a string with an xslt file" do
|
39
|
+
subject.content xml_string, :xslt => File.new('spec/files/document.xslt')
|
40
|
+
subject.new_content.should =~ /<w:t>The Departed<\/w:t>/
|
41
|
+
subject.new_content.should =~ /<w:t>The Pursuit of Happyness<\/w:t>/
|
42
|
+
end
|
43
|
+
|
44
|
+
it "accepts a string" do
|
45
|
+
subject.content 'the new content'
|
46
|
+
subject.new_content.should == 'the new content'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "accepts a file as input" do
|
50
|
+
subject.content File.new('spec/files/content.txt')
|
51
|
+
subject.new_content.should == 'this is the new content of the document'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#add_image' do
|
56
|
+
it 'adds an image to the relations file' do
|
57
|
+
subject.add_image 'rId9', 'path/to/image.jpg'
|
58
|
+
subject.new_relationships.to_s.should =~ /<Relationship Id="rId9" Type="http:\/\/schemas.openxmlformats.org\/officeDocument\/2006\/relationships\/image" Target="media\/image.jpg"\/>/
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#process" do
|
63
|
+
after :each do
|
64
|
+
File.delete 'spec/files/result.docx'
|
65
|
+
end
|
66
|
+
|
67
|
+
it "generates the resulting document" do
|
68
|
+
subject.process
|
69
|
+
File.should exist('spec/files/result.docx')
|
70
|
+
end
|
71
|
+
|
72
|
+
it "replaces the content of the document" do
|
73
|
+
subject.content 'bla'
|
74
|
+
subject.process
|
75
|
+
Zip::ZipFile.open('spec/files/result.docx') do |file|
|
76
|
+
file.get_input_stream('word/document.xml').read.should == 'bla'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'with an image' do
|
81
|
+
it 'replaces the relations file' do
|
82
|
+
subject.add_image 'rId19', 'spec/files/duck.jpeg'
|
83
|
+
subject.process
|
84
|
+
Zip::ZipFile.open('spec/files/result.docx') do |file|
|
85
|
+
content = Nokogiri::XML.parse(file.get_input_stream('word/_rels/document.xml.rels').read)
|
86
|
+
content.xpath('//r:Relationship[@Id="rId19"]', 'r' => 'http://schemas.openxmlformats.org/package/2006/relationships').first['Target'].should == 'media/duck.jpeg'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'adds the image to the resulting file' do
|
91
|
+
subject.add_image 'rId19', 'spec/files/duck.jpeg'
|
92
|
+
subject.process
|
93
|
+
Zip::ZipFile.open('spec/files/result.docx') do |file|
|
94
|
+
file.find_entry('word/media/duck.jpeg').should_not be_nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
this is the new content of the document
|
data/spec/files/data.xml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<Movies>
|
3
|
+
<Genre name="Action">
|
4
|
+
<Movie>
|
5
|
+
<Name>Crash</Name>
|
6
|
+
<Released>2005</Released>
|
7
|
+
</Movie>
|
8
|
+
</Genre>
|
9
|
+
<Genre name="Drama">
|
10
|
+
<Movie>
|
11
|
+
<Name>The Departed</Name>
|
12
|
+
<Released>2006</Released>
|
13
|
+
</Movie>
|
14
|
+
<Movie>
|
15
|
+
<Name>The Pursuit of Happyness</Name>
|
16
|
+
<Released>2006</Released>
|
17
|
+
</Movie>
|
18
|
+
</Genre>
|
19
|
+
<Genre name="Comedy">
|
20
|
+
<Movie>
|
21
|
+
<Name>The Bucket List</Name>
|
22
|
+
<Released>2007</Released>
|
23
|
+
</Movie>
|
24
|
+
</Genre>
|
25
|
+
</Movies>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
2
|
+
<xsl:template match="/">
|
3
|
+
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14">
|
4
|
+
<w:body>
|
5
|
+
<w:p w:rsidR="008E3083" w:rsidRPr="008E3083" w:rsidRDefault="008E3083"><w:pPr><w:rPr><w:b/><w:u w:val="single"/></w:rPr></w:pPr><w:r w:rsidRPr="008E3083"><w:rPr><w:b/><w:u w:val="single"/></w:rPr><w:t>Movies</w:t></w:r></w:p>
|
6
|
+
|
7
|
+
<xsl:for-each select="Movies/Genre">
|
8
|
+
<w:p w:rsidR="008E3083" w:rsidRDefault="008E3083"><w:r><w:t>
|
9
|
+
<xsl:value-of select="@name" />
|
10
|
+
</w:t></w:r></w:p>
|
11
|
+
<xsl:for-each select="Movie">
|
12
|
+
<w:p w:rsidR="008E3083" w:rsidRDefault="008E3083" w:rsidP="008E3083">
|
13
|
+
<w:pPr><w:pStyle w:val="ListParagraph"/><w:numPr><w:ilvl w:val="0"/><w:numId w:val="1"/></w:numPr></w:pPr>
|
14
|
+
<w:r><w:t><xsl:value-of select="Name" /></w:t></w:r><w:proofErr w:type="spellStart"/><w:r><w:t><xsl:value-of select="Released"/></w:t></w:r><w:proofErr w:type="spellEnd"/><w:r><w:t>)</w:t></w:r>
|
15
|
+
<w:bookmarkStart w:id="0" w:name="_GoBack"/><w:bookmarkEnd w:id="0"/>
|
16
|
+
</w:p>
|
17
|
+
</xsl:for-each>
|
18
|
+
</xsl:for-each>
|
19
|
+
<w:sectPr w:rsidR="008E3083"><w:pgSz w:w="11906" w:h="16838"/><w:pgMar w:top="1417" w:right="1417" w:bottom="1134" w:left="1417" w:header="708" w:footer="708" w:gutter="0"/><w:cols w:space="708"/><w:docGrid w:linePitch="360"/></w:sectPr>
|
20
|
+
</w:body>
|
21
|
+
</w:document>
|
22
|
+
</xsl:template>
|
23
|
+
</xsl:stylesheet>
|
Binary file
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docx_manipulator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- "Michael St\xC3\xA4mpfli"
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-04-02 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :development
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rubyzip
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: nokogiri
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id003
|
48
|
+
description: This Gem enables you to modify the contents of docx files.
|
49
|
+
email:
|
50
|
+
- michael.staempfli@gmail.com
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- .gitignore
|
59
|
+
- .rvmrc
|
60
|
+
- Gemfile
|
61
|
+
- README.rdoc
|
62
|
+
- Rakefile
|
63
|
+
- docx_manipulator.gemspec
|
64
|
+
- lib/docx_manipulator.rb
|
65
|
+
- lib/docx_manipulator/version.rb
|
66
|
+
- spec/docx_manipulator_spec.rb
|
67
|
+
- spec/files/content.txt
|
68
|
+
- spec/files/data.xml
|
69
|
+
- spec/files/document.xslt
|
70
|
+
- spec/files/duck.jpeg
|
71
|
+
- spec/files/movies.docx
|
72
|
+
homepage: ""
|
73
|
+
licenses: []
|
74
|
+
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project: docx_manipulator
|
95
|
+
rubygems_version: 1.8.11
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: Enables the modification of docx files.
|
99
|
+
test_files:
|
100
|
+
- spec/docx_manipulator_spec.rb
|
101
|
+
- spec/files/content.txt
|
102
|
+
- spec/files/data.xml
|
103
|
+
- spec/files/document.xslt
|
104
|
+
- spec/files/duck.jpeg
|
105
|
+
- spec/files/movies.docx
|