xmlresume2x 0.2.0
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/COPYING +340 -0
- data/ChangeLog +318 -0
- data/README +57 -0
- data/Rakefile +275 -0
- data/TODO +37 -0
- data/VERSION +1 -0
- data/bin/xmlresume2x +57 -0
- data/data/xmlresume2x/common/common.cfg +154 -0
- data/data/xmlresume2x/format/latex-europecv.cfg +453 -0
- data/data/xmlresume2x/format/xhtml.cfg +413 -0
- data/data/xmlresume2x/lang/de.cfg +72 -0
- data/data/xmlresume2x/lang/en.cfg +72 -0
- data/data/xmlresume2x/lang/fr.cfg +73 -0
- data/doc/src/default.css +137 -0
- data/doc/src/default.template +33 -0
- data/doc/src/download.fragment +40 -0
- data/doc/src/examples.fragment +24 -0
- data/doc/src/features.fragment +9 -0
- data/doc/src/index.fragment +29 -0
- data/doc/src/manual.fragment +135 -0
- data/doc/src/metainfo.backing +37 -0
- data/install.rb +24 -0
- data/lib/xmlresume2x/converter.rb +86 -0
- data/lib/xmlresume2x/processor.rb +135 -0
- data/lib/xmlresume2x/wrapper.rb +113 -0
- data/lib/xmlresume2x/xmlmarkup.rb +104 -0
- data/setup.rb +1331 -0
- metadata +73 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
index.html:
|
2
|
+
en:
|
3
|
+
title: Home
|
4
|
+
inMenu: true
|
5
|
+
directoryName: XMLResume2x
|
6
|
+
menuOrder: 1
|
7
|
+
|
8
|
+
download.html:
|
9
|
+
en:
|
10
|
+
title: Download & Installation
|
11
|
+
inMenu: true
|
12
|
+
menuOrder: 3
|
13
|
+
|
14
|
+
features.html:
|
15
|
+
en:
|
16
|
+
title: Features
|
17
|
+
inMenu: true
|
18
|
+
menuOrder: 5
|
19
|
+
|
20
|
+
manual.html:
|
21
|
+
en:
|
22
|
+
title: Manual
|
23
|
+
inMenu: true
|
24
|
+
menuOrder: 6
|
25
|
+
|
26
|
+
examples.html:
|
27
|
+
en:
|
28
|
+
title: Examples
|
29
|
+
inMenu: true
|
30
|
+
menuOrder: 7
|
31
|
+
|
32
|
+
api.html:
|
33
|
+
en:
|
34
|
+
dest: rdoc/index.html
|
35
|
+
title: API Reference
|
36
|
+
menuOrder: 8
|
37
|
+
inMenu: true
|
data/install.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
require 'rpa/install'
|
3
|
+
|
4
|
+
class Install_xmlresume2x < RPA::Install::FullInstaller
|
5
|
+
name 'xmlresume2x'
|
6
|
+
version '0.2.0-1'
|
7
|
+
classification Application
|
8
|
+
build do
|
9
|
+
installdocs %w[COPYING ChangeLog TODO]
|
10
|
+
installdocs 'docs'
|
11
|
+
installrdoc %w[README] + Dir['lib/**/*.rb']
|
12
|
+
installdata
|
13
|
+
end
|
14
|
+
description <<-EOF
|
15
|
+
Converts an xml resume to various output formats
|
16
|
+
|
17
|
+
xmlresume2x can convert CVs written in the XML Resume
|
18
|
+
Library format (http://xmlresume.sourceforge.net) to a number
|
19
|
+
of formats, including LaTeX markup which uses the europecv
|
20
|
+
(http://www.ctan.org/tex-archive/help/Catalogue/entries/europecv.html)
|
21
|
+
class which is based on the 'standard' European Curriculum Vitae
|
22
|
+
format at http://www.cedefop.eu.int/transparency/cv.asp.
|
23
|
+
EOF
|
24
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#
|
2
|
+
# $Id: converter.rb 23 2004-12-20 11:08:39Z thomas $
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
#
|
6
|
+
# xmlresume2x: converts an xml resume to various output formats
|
7
|
+
# Copyright (C) 2004 Thomas Leitner
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
10
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
14
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
18
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'rbconfig'
|
24
|
+
require 'erb'
|
25
|
+
require 'rexml/document'
|
26
|
+
require 'xmlresume2x/processor'
|
27
|
+
|
28
|
+
module XMLResume2x
|
29
|
+
|
30
|
+
VERSION = [0, 2, 0]
|
31
|
+
|
32
|
+
class Converter
|
33
|
+
|
34
|
+
CONFIG_EXT = '.cfg'
|
35
|
+
|
36
|
+
attr_accessor :data_dir
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
@data_dir = File.join( Config::CONFIG["datadir"], "xmlresume2x" )
|
40
|
+
if defined? Gem::Cache
|
41
|
+
gem = Gem::Cache.from_installed_gems.search( "xmlresume2x", "=#{VERSION.join('.')}" ).last
|
42
|
+
@data_dir = File.join( gem.full_gem_path, "data", "xmlresume2x" ) if gem
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def available_formats
|
47
|
+
dir_list( format_dir )
|
48
|
+
end
|
49
|
+
|
50
|
+
def available_langs
|
51
|
+
dir_list( lang_dir )
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_config( format, lang, userconfig = nil )
|
55
|
+
@processor = ResumeProcessor.new( lang )
|
56
|
+
|
57
|
+
filename = File.join( format_dir, format + CONFIG_EXT )
|
58
|
+
@processor.load_config( File.read( filename ), filename)
|
59
|
+
|
60
|
+
filename = File.join( lang_dir, lang + CONFIG_EXT )
|
61
|
+
@processor.load_config( File.read( filename ), filename )
|
62
|
+
|
63
|
+
@processor.load_config( File.read( userconfig ), userconfig ) if userconfig
|
64
|
+
end
|
65
|
+
|
66
|
+
def convert( resume )
|
67
|
+
ElementWrapper.new( REXML::Document.new( File.new( resume ) ).root, @processor, {} ).process!
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def format_dir
|
73
|
+
File.join( @data_dir, 'format' )
|
74
|
+
end
|
75
|
+
|
76
|
+
def lang_dir
|
77
|
+
File.join( @data_dir, 'lang' )
|
78
|
+
end
|
79
|
+
|
80
|
+
def dir_list( dir )
|
81
|
+
Dir[File.join( dir, '*' + CONFIG_EXT )].collect {|name| File.basename( name, CONFIG_EXT ) }
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#
|
2
|
+
# $Id: processor.rb 21 2004-12-09 17:44:52Z thomas $
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
#
|
6
|
+
# xmlresume2x: converts an xml resume to various output formats
|
7
|
+
# Copyright (C) 2004 Thomas Leitner
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
10
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
14
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
18
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'xmlresume2x/wrapper'
|
24
|
+
|
25
|
+
module XMLResume2x
|
26
|
+
|
27
|
+
# This class serves as container for processors and keywords. Therefore it defines the methods
|
28
|
+
# which can be used in the configuration files.
|
29
|
+
class ResumeProcessor
|
30
|
+
|
31
|
+
# A hash of processors
|
32
|
+
attr_reader :processors
|
33
|
+
|
34
|
+
# A hash containing the assignments of XML elements to processors
|
35
|
+
attr_reader :assignments
|
36
|
+
|
37
|
+
# The language used for this ResumeProcessor
|
38
|
+
attr_accessor :lang
|
39
|
+
|
40
|
+
def initialize( lang )
|
41
|
+
@lang = lang
|
42
|
+
@keywords = Hash.new( '<UNDEFINED>' )
|
43
|
+
@processors = Hash.new( Proc.new {|e, options| get_children_value( e, options ) } )
|
44
|
+
@assignments = Hash.new
|
45
|
+
processor( :textItem => 'REXMLTextProcessor' ) {|e, options| get_value( e.value, options ) }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Loads the configuration defined by the given string +src+.
|
49
|
+
def load_config( src, filename = '(eval)' )
|
50
|
+
instance_eval( src, filename )
|
51
|
+
end
|
52
|
+
|
53
|
+
# Adds a processor which should be defined using a block. +name+ is the name of the processor.
|
54
|
+
def add_processor( name, &block )
|
55
|
+
raise ArgumentError, "No block given" unless block_given?
|
56
|
+
@processors[name.to_s] = block
|
57
|
+
end
|
58
|
+
|
59
|
+
# Assigns elements to processors. +assignment+ has to be a Hash where the keys are XML resume
|
60
|
+
# element names and the values are processor names. If a block is supplied, then the XML resume
|
61
|
+
# elements are processed by the given block.
|
62
|
+
def processor( assignment, &block )
|
63
|
+
raise ArgumentError, "Argument has to be a Hash" unless Hash === assignment
|
64
|
+
assignment.each do |key, value|
|
65
|
+
add_processor( value, &block ) if block_given?
|
66
|
+
case key
|
67
|
+
when Array
|
68
|
+
key.each {|name| @assignments[name.to_s] = value }
|
69
|
+
when String
|
70
|
+
@assignments[key.to_s] = value
|
71
|
+
when Symbol
|
72
|
+
@assignments[key] = value
|
73
|
+
else
|
74
|
+
raise ArgumentError, "Key for assignment has to be Array or String or Symbol"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Calls the processor +name+ on the element +item+ and optionally with +options+.
|
80
|
+
def call_processor( name, item, options = {} )
|
81
|
+
proc = @processors[name]
|
82
|
+
if proc.arity == 1
|
83
|
+
proc.call( item )
|
84
|
+
else
|
85
|
+
proc.call( item, options )
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Defines or retrieves a keyword. If +arg+ is a Hash, then the keywords in this Hash are added.
|
90
|
+
# If +arg+ is a Symbol, then the specified keyword is retrieved. The parameter +processed+
|
91
|
+
# specifies if the keyword should be processed as any other text.
|
92
|
+
def keyword( arg, processed = true )
|
93
|
+
case arg
|
94
|
+
when Symbol
|
95
|
+
processed ? get_value( @keywords[arg] ) : @keywords[arg]
|
96
|
+
when Hash
|
97
|
+
@keywords.update( arg )
|
98
|
+
else
|
99
|
+
raise ArgumentError, "Argument has to be a Symbol or a Hash"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns the value of +item+ after being processed by the assigned processor.
|
104
|
+
def get_value( item, options = {} )
|
105
|
+
name, item = case item
|
106
|
+
when ElementWrapper
|
107
|
+
options = item.options.merge( options )
|
108
|
+
[item.__element.name, item]
|
109
|
+
when REXML::Element
|
110
|
+
[item.name, ElementWrapper.new( item, self, options )]
|
111
|
+
when REXML::Text
|
112
|
+
[:textItem, item]
|
113
|
+
when String
|
114
|
+
[:text, item]
|
115
|
+
when NilClass
|
116
|
+
return nil
|
117
|
+
else
|
118
|
+
raise ArgumentError, "Not a valid argument class (#{item.class})"
|
119
|
+
end
|
120
|
+
call_processor( @assignments[name], item, options )
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns the values of the processed children of +element+.
|
124
|
+
# *Returns*:: an array with all the values or if the <tt>:to_s</tt>
|
125
|
+
# option is set, the array converted to a string, i.e. <tt>array.to_s</tt>
|
126
|
+
def get_children_value( element, options = {} )
|
127
|
+
arr = []
|
128
|
+
new_options = element.options.merge( options )
|
129
|
+
element.__element.each_child {|child| arr << get_value( child, new_options ) }
|
130
|
+
new_options[:to_s] ? arr.to_s : arr
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
#
|
2
|
+
# $Id: wrapper.rb 22 2004-12-10 18:21:39Z thomas $
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
#
|
6
|
+
# xmlresume2x: converts an xml resume to various output formats
|
7
|
+
# Copyright (C) 2004 Thomas Leitner
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
10
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
14
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
18
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
class Array
|
24
|
+
|
25
|
+
alias_method :old_join, :join
|
26
|
+
def join( sep = $, )
|
27
|
+
if sep.instance_of?( String ) || sep.instance_of?( NilClass )
|
28
|
+
old_join( sep )
|
29
|
+
else
|
30
|
+
arr = []
|
31
|
+
self.each_with_index {|e, i| arr << sep.clone if i > 0; arr << e}
|
32
|
+
arr
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def separate_by( sep, sepLast )
|
37
|
+
result = self[0..-2].join( sep )
|
38
|
+
case self.length
|
39
|
+
when 0 then result
|
40
|
+
when 1 then self.last
|
41
|
+
when 2
|
42
|
+
if result.kind_of? String
|
43
|
+
result << sepLast.to_s << self.last.to_s
|
44
|
+
else
|
45
|
+
result << sepLast << self.last
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
module XMLResume2x
|
53
|
+
|
54
|
+
class ElementWrapperList < Array
|
55
|
+
|
56
|
+
def method_missing( name, *args )
|
57
|
+
return nil if self.length == 0
|
58
|
+
self[0].send( name.to_s, *args )
|
59
|
+
end
|
60
|
+
|
61
|
+
def process_all!( options = {} )
|
62
|
+
self.collect {|e| e.process!( options ) }
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class ElementWrapper
|
68
|
+
|
69
|
+
attr_reader :options
|
70
|
+
|
71
|
+
def initialize( element, processor, options )
|
72
|
+
@element = element
|
73
|
+
@processor = processor
|
74
|
+
@options = options
|
75
|
+
end
|
76
|
+
|
77
|
+
def method_missing( name, *args )
|
78
|
+
name = name.to_s
|
79
|
+
if name =~ /^_/
|
80
|
+
name.sub!( /^_/, '' )
|
81
|
+
@processor.get_value( @element.attributes[name], @options )
|
82
|
+
elsif @element.elements[name]
|
83
|
+
list = ElementWrapperList.new
|
84
|
+
@element.each_element( name ) {|e| list << ElementWrapper.new( e, @processor, @options ) }
|
85
|
+
list
|
86
|
+
else
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def __element
|
92
|
+
@element
|
93
|
+
end
|
94
|
+
|
95
|
+
def process!( options = {} )
|
96
|
+
@processor.get_value( self, options )
|
97
|
+
end
|
98
|
+
|
99
|
+
def process_children!( options = {} )
|
100
|
+
@processor.get_children_value( self, options )
|
101
|
+
end
|
102
|
+
|
103
|
+
def text!
|
104
|
+
@processor.get_value( @element.text, @options )
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_s
|
108
|
+
process!.to_s
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
#
|
2
|
+
# $Id: xmlmarkup.rb 22 2004-12-10 18:21:39Z thomas $
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
#
|
6
|
+
# xmlresume2x: converts an xml resume to various output formats
|
7
|
+
# Copyright (C) 2004 Thomas Leitner
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
10
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
14
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
18
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
|
24
|
+
class XMLResume2x::ResumeProcessor
|
25
|
+
|
26
|
+
def tag( name, attr = nil, context = nil )
|
27
|
+
e = REXML::Element.new( name, context )
|
28
|
+
attr.each {|key, value| e.add_attribute( key, value )} if attr
|
29
|
+
e
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class REXML::Parent
|
35
|
+
|
36
|
+
alias_method :old_add, :add
|
37
|
+
|
38
|
+
def add( object, *others )
|
39
|
+
if object.instance_of?( XMLResume2x::ElementWrapper ) || object.instance_of?( XMLResume2x::ElementWrapperList )
|
40
|
+
add( object.process! )
|
41
|
+
elsif object.instance_of? XMLResume2x::REXMLBuilder
|
42
|
+
add( object.element! )
|
43
|
+
elsif object.instance_of? Array
|
44
|
+
object.each {|o| add( o )}
|
45
|
+
elsif object.instance_of? String
|
46
|
+
old_add( REXML::Text.new( object ) )
|
47
|
+
else
|
48
|
+
old_add( object )
|
49
|
+
end
|
50
|
+
others.each {|o| add( o )}
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
class REXML::Element
|
57
|
+
|
58
|
+
def builder
|
59
|
+
XMLResume2x::REXMLBuilder.new( self )
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
class XMLResume2x::REXMLBuilder
|
66
|
+
|
67
|
+
instance_methods.each {|m| undef_method( m ) unless m =~ /^(__|instance_eval)|\?$/}
|
68
|
+
|
69
|
+
def initialize( element )
|
70
|
+
@element = element
|
71
|
+
end
|
72
|
+
|
73
|
+
def method_missing( name, *args, &block )
|
74
|
+
attrs = {}
|
75
|
+
content = nil
|
76
|
+
args.each do |a|
|
77
|
+
if a.instance_of? Hash
|
78
|
+
attrs.merge!( a )
|
79
|
+
else
|
80
|
+
content ||= []
|
81
|
+
content << a
|
82
|
+
end
|
83
|
+
end
|
84
|
+
new_elem = @element.add_element( name.to_s, attrs )
|
85
|
+
new_elem.add( content ) unless content.nil?
|
86
|
+
yield XMLResume2x::REXMLBuilder.new( new_elem ) if block_given?
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
def text!( str )
|
91
|
+
@element.add_text( str )
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def add!( object, *others )
|
96
|
+
@element.add( object, *others )
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
def element!
|
101
|
+
@element
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|