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