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.
@@ -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
@@ -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