docx_manipulator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|