pdf-labels 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/History.txt +8 -0
  2. data/LICENCE +38 -0
  3. data/Manifest.txt +141 -0
  4. data/README.txt +72 -0
  5. data/Rakefile +30 -0
  6. data/lib/alias.rb +8 -0
  7. data/lib/glabel_template.rb +36 -0
  8. data/lib/label.rb +52 -0
  9. data/lib/layout.rb +13 -0
  10. data/lib/length_node.rb +47 -0
  11. data/lib/markup.rb +25 -0
  12. data/lib/pdf_label_page.rb +171 -0
  13. data/lib/pdf_labels.rb +6 -0
  14. data/lib/template.rb +37 -0
  15. data/templates/avery-iso-templates.xml +222 -0
  16. data/templates/avery-other-templates.xml +21 -0
  17. data/templates/avery-us-templates.xml +599 -0
  18. data/templates/glabels-2.0.dtd +329 -0
  19. data/templates/misc-iso-templates.xml +434 -0
  20. data/templates/misc-other-templates.xml +21 -0
  21. data/templates/misc-us-templates.xml +183 -0
  22. data/templates/paper-sizes.xml +37 -0
  23. data/templates/zweckform-iso-templates.xml +197 -0
  24. data/test/test_pdf_label_page.rb +91 -0
  25. data/vendor/color.rb +87 -0
  26. data/vendor/color/cmyk.rb +182 -0
  27. data/vendor/color/css.rb +27 -0
  28. data/vendor/color/grayscale.rb +135 -0
  29. data/vendor/color/hsl.rb +130 -0
  30. data/vendor/color/palette.rb +15 -0
  31. data/vendor/color/palette/gimp.rb +107 -0
  32. data/vendor/color/palette/monocontrast.rb +180 -0
  33. data/vendor/color/rgb-colors.rb +189 -0
  34. data/vendor/color/rgb.rb +311 -0
  35. data/vendor/color/rgb/metallic.rb +28 -0
  36. data/vendor/color/yiq.rb +78 -0
  37. data/vendor/pdf/charts.rb +13 -0
  38. data/vendor/pdf/charts/stddev.rb +433 -0
  39. data/vendor/pdf/grid.rb +135 -0
  40. data/vendor/pdf/math.rb +108 -0
  41. data/vendor/pdf/pagenumbers.rb +288 -0
  42. data/vendor/pdf/quickref.rb +331 -0
  43. data/vendor/pdf/simpletable.rb +947 -0
  44. data/vendor/pdf/techbook.rb +901 -0
  45. data/vendor/pdf/writer.rb +2801 -0
  46. data/vendor/pdf/writer/arc4.rb +63 -0
  47. data/vendor/pdf/writer/fontmetrics.rb +202 -0
  48. data/vendor/pdf/writer/fonts/Courier-Bold.afm +342 -0
  49. data/vendor/pdf/writer/fonts/Courier-BoldOblique.afm +342 -0
  50. data/vendor/pdf/writer/fonts/Courier-Oblique.afm +342 -0
  51. data/vendor/pdf/writer/fonts/Courier.afm +342 -0
  52. data/vendor/pdf/writer/fonts/Helvetica-Bold.afm +2827 -0
  53. data/vendor/pdf/writer/fonts/Helvetica-BoldOblique.afm +2827 -0
  54. data/vendor/pdf/writer/fonts/Helvetica-Oblique.afm +3051 -0
  55. data/vendor/pdf/writer/fonts/Helvetica.afm +3051 -0
  56. data/vendor/pdf/writer/fonts/Symbol.afm +213 -0
  57. data/vendor/pdf/writer/fonts/Times-Bold.afm +2588 -0
  58. data/vendor/pdf/writer/fonts/Times-BoldItalic.afm +2384 -0
  59. data/vendor/pdf/writer/fonts/Times-Italic.afm +2667 -0
  60. data/vendor/pdf/writer/fonts/Times-Roman.afm +2419 -0
  61. data/vendor/pdf/writer/fonts/ZapfDingbats.afm +225 -0
  62. data/vendor/pdf/writer/graphics.rb +813 -0
  63. data/vendor/pdf/writer/graphics/imageinfo.rb +365 -0
  64. data/vendor/pdf/writer/lang.rb +44 -0
  65. data/vendor/pdf/writer/lang/en.rb +104 -0
  66. data/vendor/pdf/writer/object.rb +23 -0
  67. data/vendor/pdf/writer/object/action.rb +40 -0
  68. data/vendor/pdf/writer/object/annotation.rb +42 -0
  69. data/vendor/pdf/writer/object/catalog.rb +39 -0
  70. data/vendor/pdf/writer/object/contents.rb +69 -0
  71. data/vendor/pdf/writer/object/destination.rb +40 -0
  72. data/vendor/pdf/writer/object/encryption.rb +53 -0
  73. data/vendor/pdf/writer/object/font.rb +68 -0
  74. data/vendor/pdf/writer/object/fontdescriptor.rb +34 -0
  75. data/vendor/pdf/writer/object/fontencoding.rb +40 -0
  76. data/vendor/pdf/writer/object/image.rb +308 -0
  77. data/vendor/pdf/writer/object/info.rb +79 -0
  78. data/vendor/pdf/writer/object/outline.rb +30 -0
  79. data/vendor/pdf/writer/object/outlines.rb +30 -0
  80. data/vendor/pdf/writer/object/page.rb +195 -0
  81. data/vendor/pdf/writer/object/pages.rb +115 -0
  82. data/vendor/pdf/writer/object/procset.rb +46 -0
  83. data/vendor/pdf/writer/object/viewerpreferences.rb +74 -0
  84. data/vendor/pdf/writer/ohash.rb +58 -0
  85. data/vendor/pdf/writer/oreader.rb +25 -0
  86. data/vendor/pdf/writer/state.rb +48 -0
  87. data/vendor/pdf/writer/strokestyle.rb +140 -0
  88. data/vendor/transaction/simple.rb +693 -0
  89. data/vendor/transaction/simple/group.rb +133 -0
  90. data/vendor/transaction/simple/threadsafe.rb +52 -0
  91. data/vendor/transaction/simple/threadsafe/group.rb +23 -0
  92. data/vendor/xml-mapping/ChangeLog +128 -0
  93. data/vendor/xml-mapping/LICENSE +56 -0
  94. data/vendor/xml-mapping/README +386 -0
  95. data/vendor/xml-mapping/README_XPATH +175 -0
  96. data/vendor/xml-mapping/Rakefile +214 -0
  97. data/vendor/xml-mapping/TODO.txt +32 -0
  98. data/vendor/xml-mapping/doc/xpath_impl_notes.txt +119 -0
  99. data/vendor/xml-mapping/examples/company.rb +34 -0
  100. data/vendor/xml-mapping/examples/company.xml +26 -0
  101. data/vendor/xml-mapping/examples/company_usage.intin.rb +19 -0
  102. data/vendor/xml-mapping/examples/company_usage.intout +39 -0
  103. data/vendor/xml-mapping/examples/order.rb +61 -0
  104. data/vendor/xml-mapping/examples/order.xml +54 -0
  105. data/vendor/xml-mapping/examples/order_signature_enhanced.rb +7 -0
  106. data/vendor/xml-mapping/examples/order_signature_enhanced.xml +9 -0
  107. data/vendor/xml-mapping/examples/order_signature_enhanced_usage.intin.rb +12 -0
  108. data/vendor/xml-mapping/examples/order_signature_enhanced_usage.intout +16 -0
  109. data/vendor/xml-mapping/examples/order_usage.intin.rb +73 -0
  110. data/vendor/xml-mapping/examples/order_usage.intout +147 -0
  111. data/vendor/xml-mapping/examples/time_augm.intin.rb +19 -0
  112. data/vendor/xml-mapping/examples/time_augm.intout +23 -0
  113. data/vendor/xml-mapping/examples/time_node.rb +27 -0
  114. data/vendor/xml-mapping/examples/xpath_create_new.intin.rb +85 -0
  115. data/vendor/xml-mapping/examples/xpath_create_new.intout +181 -0
  116. data/vendor/xml-mapping/examples/xpath_docvsroot.intin.rb +30 -0
  117. data/vendor/xml-mapping/examples/xpath_docvsroot.intout +34 -0
  118. data/vendor/xml-mapping/examples/xpath_ensure_created.intin.rb +62 -0
  119. data/vendor/xml-mapping/examples/xpath_ensure_created.intout +114 -0
  120. data/vendor/xml-mapping/examples/xpath_pathological.intin.rb +42 -0
  121. data/vendor/xml-mapping/examples/xpath_pathological.intout +56 -0
  122. data/vendor/xml-mapping/examples/xpath_usage.intin.rb +51 -0
  123. data/vendor/xml-mapping/examples/xpath_usage.intout +57 -0
  124. data/vendor/xml-mapping/install.rb +40 -0
  125. data/vendor/xml-mapping/lib/xml/mapping.rb +14 -0
  126. data/vendor/xml-mapping/lib/xml/mapping/base.rb +571 -0
  127. data/vendor/xml-mapping/lib/xml/mapping/standard_nodes.rb +343 -0
  128. data/vendor/xml-mapping/lib/xml/mapping/version.rb +8 -0
  129. data/vendor/xml-mapping/lib/xml/xxpath.rb +354 -0
  130. data/vendor/xml-mapping/test/all_tests.rb +6 -0
  131. data/vendor/xml-mapping/test/company.rb +56 -0
  132. data/vendor/xml-mapping/test/documents_folders.rb +33 -0
  133. data/vendor/xml-mapping/test/fixtures/bookmarks1.xml +24 -0
  134. data/vendor/xml-mapping/test/fixtures/company1.xml +85 -0
  135. data/vendor/xml-mapping/test/fixtures/documents_folders.xml +71 -0
  136. data/vendor/xml-mapping/test/fixtures/documents_folders2.xml +30 -0
  137. data/vendor/xml-mapping/test/multiple_mappings.rb +80 -0
  138. data/vendor/xml-mapping/test/tests_init.rb +2 -0
  139. data/vendor/xml-mapping/test/xml_mapping_adv_test.rb +84 -0
  140. data/vendor/xml-mapping/test/xml_mapping_test.rb +201 -0
  141. data/vendor/xml-mapping/test/xpath_test.rb +273 -0
  142. metadata +191 -0
@@ -0,0 +1,175 @@
1
+ = XML-XXPATH
2
+
3
+ == Overview, Motivation
4
+
5
+ Xml-xxpath is an (incomplete) XPath interpreter that is at the moment
6
+ bundled with xml-mapping. It is built on top of REXML. xml-mapping
7
+ uses xml-xxpath extensively for implementing its node types -- see the
8
+ README file and the reference documentation (and the source code) for
9
+ details. xml-xxpath, however, does not depend on xml-mapping at all,
10
+ and is useful in its own right -- maybe I'll later distribute it as a
11
+ seperate library instead of bundling it. xml-xxpath's XPath support is
12
+ vastly incomplete (see below), but, in addition to the normal
13
+ reading/matching functionality found in other XPath implementations
14
+ (i.e. "find all elements in a given XML document matching a given
15
+ XPath expression"), xml-xxpath supports <i>write access</i>. For
16
+ example, when writing the XPath expression
17
+ "/foo/bar[3]/baz[@key='hiho']" to the XML document
18
+
19
+ <foo>
20
+ <bar>
21
+ <baz key='ab'>hello</baz>
22
+ <baz key='xy'>goodbye</baz>
23
+ </bar>
24
+ </foo>
25
+
26
+ , you'll get:
27
+
28
+ <foo>
29
+ <bar>
30
+ <baz key='ab'>hello</baz>
31
+ <baz key='xy'>goodbye</baz>
32
+ </bar>
33
+ <bar/>
34
+ <bar><baz key='hiho'/></bar>
35
+ </foo>
36
+
37
+ This feature is used by xml-mapping when writing (marshalling) Ruby
38
+ objects to XML, and is actually the reason why I couldn't just use any
39
+ of the existing XPath implementations, e.g. the one that comes with
40
+ REXML. Also, the whole xml-xxpath implementation is just 300 lines of
41
+ Ruby code, it is quite fast (paths are precompiled), and xml-xxpath
42
+ returns matched elements in the order they appeared in the source
43
+ document -- I've heard REXML::XXPath doesn't do that :)
44
+
45
+ Some basic knowledge of XPath is helpful for reading this document (I
46
+ don't know very much either).
47
+
48
+ At the moment, xml-xxpath understands XPath expressions of the form
49
+ [<tt>/</tt>]_pathelement_<tt>/</tt>_pathelement_<tt>/</tt>..., where
50
+ each _pathelement_ must be one of these:
51
+
52
+ - a simple element name _name_, e.g. +signature+
53
+
54
+ - an attribute name, @_attr_name_, e.g. <tt>@key</tt>
55
+
56
+ - a combination of an element name and an attribute name and
57
+ -value, in the form _elt_name_[@_attr_name_='_attr_value_']
58
+
59
+ - an element name and an index, _elt_name_[_index_]
60
+
61
+ - the "match-all" path element, <tt>*</tt>
62
+
63
+
64
+ == Usage
65
+
66
+ Xml-xxpath defines the class XML::XXPath. An instance of that class
67
+ wraps an XPath expression, the string representation of which must be
68
+ supplied when constructing the instance. You then call instance
69
+ methods like _first_, _all_ or <i>create_new</i> on the instance,
70
+ supplying the REXML Element the XPath expression should be applied to,
71
+ and get the results, or, in the case of write access, the element is
72
+ updated in-place.
73
+
74
+
75
+ === Read Access
76
+
77
+ :include: xpath_usage.intout
78
+
79
+ The objects supplied to the <tt>all()</tt>, <tt>first()</tt>, and
80
+ <tt>each()</tt> calls must be REXML element nodes, i.e. they must
81
+ support messages like <tt>elements</tt>, <tt>attributes</tt> etc
82
+ (instances of REXML::Element and its subclasses do this). The calls
83
+ return the found elements as instances of REXML::Element or
84
+ XML::XXPath::Accessors::Attribute. The latter is a wrapper around
85
+ attribute nodes that is largely call-compatible to
86
+ REXML::Element. This is so you can write things like
87
+ <tt>path.each{|node|puts node.text}</tt> without having to
88
+ special-case anything even if the path matches attributes, not just
89
+ elements.
90
+
91
+ As you can see, you can re-use path objects, applying them to
92
+ different XML elements at will. You should do this because the XPath
93
+ pattern is stored inside the XPath object in a pre-compiled form,
94
+ which makes it more efficient.
95
+
96
+ The path elements of the XPath pattern are applied to the
97
+ <tt>.elements</tt> collection of the passed XML element and its
98
+ sub-elements, starting with the first one. This is shown by the
99
+ following code:
100
+
101
+ :include: xpath_docvsroot.intout
102
+
103
+ A REXML +Document+ object is a REXML +Element+ object whose +elements+
104
+ collection consists only of a single member -- the document's root
105
+ node. The first path element of the XPath -- "foo" in the example --
106
+ is matched against that. That is why the path "/bar" in the example
107
+ doesn't match anything when matched against the document +d+ itself.
108
+
109
+ An ordinary REXML +Element+ object that represents a node somewhere
110
+ inside an XML tree has an +elements+ collection that consists of all
111
+ the element's direct sub-elements. That is why XPath patterns matched
112
+ against the +firstelt+ element in the example *must not* start with
113
+ "/first" (unless there is a child node that is also named "first").
114
+
115
+
116
+ === Write Access
117
+
118
+ You may pass a <tt>:ensure_created=>true</tt> option argument to
119
+ _path_.first(_elt_)/_path_.all(_elt_) calls to make sure that _path_
120
+ exists inside the passed XML element _elt_. If it existed before,
121
+ nothing changes, and the call behaves just as it would without the
122
+ option argument. If the path didn't exist before, the XML element is
123
+ modified such that
124
+
125
+ - the path exists afterwards
126
+
127
+ - all paths that existed before still exist afterwards
128
+
129
+ - the modification is as small as possible (i.e. as few elements as
130
+ possible are added, additional attributes are added to existing
131
+ elements if possible etc.)
132
+
133
+ The created resp. previously existing, matching elements are returned.
134
+
135
+
136
+ Examples:
137
+
138
+ :include: xpath_ensure_created.intout
139
+
140
+
141
+ Alternatively, you may pass a <tt>:create_new=>true</tt> option
142
+ argument or call <tt>create_new</tt> (_path_.create_new(_elt_) is
143
+ equivalent to _path_.first(_elt_,:create_new=>true)). In that case, a
144
+ new node in created in _elt_ for each path element of _path_ (or an
145
+ exception raised if that wasn't possible for any path element).
146
+
147
+ Examples:
148
+
149
+ :include: xpath_create_new.intout
150
+
151
+
152
+ === Pathological Cases
153
+
154
+ What is created when the Path "*" is to be created inside an empty XML
155
+ element? The name of the element to be created isn't known, but still
156
+ some element must be created. The answer is that xml-xxpath creates a
157
+ special "unspecified" element whose name must be set by the caller
158
+ afterwards:
159
+
160
+ :include: xpath_pathological.intout
161
+
162
+ The "newelt" object in the last example is an ordinary
163
+ REXML::Element. xml-xxpath mixes the "unspecified" attribute into that
164
+ class, as well as into the XML::XXPath::Accessors::Attribute class
165
+ mentioned above.
166
+
167
+
168
+ == Implentation notes
169
+
170
+ <tt>doc/xpath_impl_notes.txt</tt> contains some documentation on the
171
+ implementation of xml-xxpath.
172
+
173
+ == License
174
+
175
+ Ruby's.
@@ -0,0 +1,214 @@
1
+ # -*- ruby -*-
2
+ # adapted from active_record's Rakefile
3
+
4
+ require 'rubygems'
5
+ require 'rake'
6
+ require 'rake/testtask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/packagetask'
9
+ require 'rake/gempackagetask'
10
+ #require 'rake/contrib/rubyforgepublisher'
11
+ require 'rake/contrib/sshpublisher'
12
+
13
+ require File.dirname(__FILE__)+"/lib/xml/mapping/version"
14
+
15
+
16
+ # yeah -- it's just stupid that these are private
17
+
18
+ class Rake::RDocTask
19
+ public :rdoc_target
20
+ end
21
+
22
+ class Rake::PackageTask
23
+ public :tgz_file, :zip_file
24
+ end
25
+
26
+ class Rake::GemPackageTask
27
+ public :gem_file
28
+ end
29
+
30
+
31
+ FILES_RDOC_EXTRA=%w{README README_XPATH TODO.txt doc/xpath_impl_notes.txt}
32
+ FILES_RDOC_INCLUDES=%w{examples/company.xml
33
+ examples/company.rb
34
+ examples/company_usage.intout
35
+ examples/order_usage.intout
36
+ examples/time_augm.intout
37
+ examples/xpath_usage.intout
38
+ examples/xpath_ensure_created.intout
39
+ examples/xpath_create_new.intout
40
+ examples/xpath_pathological.intout
41
+ examples/xpath_docvsroot.intout
42
+ examples/order_signature_enhanced_usage.intout}
43
+
44
+
45
+ desc "Default Task"
46
+ task :default => [ :test ]
47
+
48
+ Rake::TestTask.new(:test) { |t|
49
+ t.test_files = ["test/all_tests.rb"]
50
+ t.verbose = true
51
+ }
52
+
53
+ # runs tests only if sources have changed since last succesful run of
54
+ # tests
55
+ file "test_run" => FileList.new('lib/**/*.rb','test/**/*.rb') do
56
+ Task[:test].invoke
57
+ touch "test_run"
58
+ end
59
+
60
+
61
+
62
+ Rake::RDocTask.new { |rdoc|
63
+ rdoc.rdoc_dir = 'doc/api'
64
+ rdoc.title = "XML::Mapping -- Simple, extensible Ruby-to-XML (and back) mapper"
65
+ rdoc.options << '--line-numbers --inline-source --accessor cattr_accessor=object --include examples'
66
+ rdoc.rdoc_files.include(*FILES_RDOC_EXTRA)
67
+ rdoc.rdoc_files.include('lib/**/*.rb')
68
+
69
+ # additional file dependencies for the rdoc task
70
+ # this somewhat of a black art because RDocTask doesn't document the
71
+ # prerequisite of its rdoc task (<rdoc_dir>/index.html)
72
+ file rdoc.rdoc_target => FILES_RDOC_INCLUDES
73
+ file "#{rdoc.rdoc_dir}/index.html" => FileList.new("examples/**/*.rb")
74
+ }
75
+
76
+ #rule '.intout' => ['.intin.rb', *FileList.new("lib/**/*.rb")] do |task| # doesn't work -- see below
77
+ rule '.intout' => ['.intin.rb'] do |task|
78
+ this_file_re = Regexp.compile(Regexp.quote(__FILE__))
79
+ b = binding
80
+ visible=true; visible_retval=true; handle_exceptions=false
81
+ old_stdout = $stdout
82
+ old_wd = Dir.pwd
83
+ begin
84
+ File.open(task.name,"w") do |fout|
85
+ $stdout = fout
86
+ File.open(task.source,"r") do |fin|
87
+ Dir.chdir File.dirname(task.name)
88
+ fin.read.split("#<=\n").each do |snippet|
89
+
90
+ snippet.scan(/^#:(.*?):$/) do |(switch,)|
91
+ case switch
92
+ when "visible"
93
+ visible=true
94
+ when "invisible"
95
+ visible=false
96
+ when "visible_retval"
97
+ visible_retval=true
98
+ when "invisible_retval"
99
+ visible_retval=false
100
+ when "handle_exceptions"
101
+ handle_exceptions=true
102
+ when "no_exceptions"
103
+ handle_exceptions=false
104
+ end
105
+ end
106
+ snippet.gsub!(/^#:.*?:(?:\n|\z)/,'')
107
+
108
+ print "#{snippet}\n" if visible
109
+ exc_handled = false
110
+ value = begin
111
+ eval(snippet,b)
112
+ rescue Exception
113
+ raise unless handle_exceptions
114
+ exc_handled = true
115
+ if visible
116
+ print "#{$!.class}: #{$!}\n"
117
+ for m in $@
118
+ break if m=~this_file_re
119
+ print "\tfrom #{m}\n"
120
+ end
121
+ end
122
+ end
123
+ if visible and visible_retval and not exc_handled
124
+ print "=> #{value.inspect}\n"
125
+ end
126
+ end
127
+ end
128
+ end
129
+ rescue Exception
130
+ $stdout = old_stdout
131
+ Dir.chdir old_wd
132
+ File.delete task.name
133
+ raise
134
+ ensure
135
+ $stdout = old_stdout
136
+ Dir.chdir old_wd
137
+ end
138
+ end
139
+
140
+ # have to add additional prerequisites manually because it appears
141
+ # that rules can only define a single prerequisite :-\
142
+ for f in %w{examples/company_usage
143
+ examples/order_usage
144
+ examples/order_signature_enhanced_usage
145
+ examples/time_augm
146
+ examples/xpath_usage
147
+ examples/xpath_ensure_created
148
+ examples/xpath_create_new
149
+ examples/xpath_pathological
150
+ examples/xpath_docvsroot} do
151
+ file "#{f}.intout" => ["#{f}.intin.rb", 'examples/company.xml']
152
+ file "#{f}.intout" => FileList.new("lib/**/*.rb")
153
+ file "#{f}.intout" => FileList.new("examples/**/*.rb")
154
+ end
155
+
156
+
157
+ spec = Gem::Specification.new do |s|
158
+ s.name = 'xml-mapping'
159
+ s.version = XML::Mapping::VERSION
160
+ s.platform = Gem::Platform::RUBY
161
+ s.summary =
162
+ "An easy to use, extensible library for mapping Ruby objects to XML and back. Includes an XPath interpreter."
163
+
164
+ # Rubygems' RDoc support is incomplete... Can't seem to find a way
165
+ # to set the start page, or a set of files that should be includable
166
+ # but not processed by rdoc directly
167
+ s.files += FILES_RDOC_EXTRA
168
+ s.files += Dir.glob("{lib,examples,test}/**/*").delete_if do |item|
169
+ item.include?("CVS") || item =~ /~$/
170
+ end
171
+ s.files += %w{LICENSE Rakefile ChangeLog install.rb}
172
+ s.extra_rdoc_files = FILES_RDOC_EXTRA
173
+ s.rdoc_options += %w{--include examples}
174
+
175
+ s.require_path = 'lib'
176
+ s.autorequire = 'xml/mapping'
177
+
178
+ # s.add_dependency 'rexml'
179
+
180
+ s.has_rdoc=true
181
+
182
+ s.test_file = 'test/all_tests.rb'
183
+
184
+ s.author = 'Olaf Klischat'
185
+ s.email = 'klischat@cs.tu-berlin.de'
186
+ s.homepage = "http://xml-mapping.rubyforge.org"
187
+ end
188
+
189
+
190
+
191
+ Rake::GemPackageTask.new(spec) do |p|
192
+ p.gem_spec = spec
193
+ p.need_tar = true
194
+ p.need_zip = true
195
+
196
+ # (indirectly) add :rdoc, :test as prerequisites to :package task
197
+ # created by GemPackageTask
198
+ file "#{p.package_dir}/#{p.tgz_file}" => [ "test_run", :rdoc ]
199
+ file "#{p.package_dir}/#{p.zip_file}" => [ "test_run", :rdoc ]
200
+ file "#{p.package_dir}/#{p.gem_file}" => [ "test_run", :rdoc ]
201
+ end
202
+
203
+
204
+
205
+ # run "rake package" to generate tgz, zip, gem in pkg/
206
+
207
+
208
+
209
+ task :rfpub_rdoc => [:rdoc] do
210
+ p=Rake::SshDirPublisher.new('xml-mapping.rubyforge.org',
211
+ '/var/www/gforge-projects/xml-mapping/',
212
+ 'doc/api')
213
+ p.upload
214
+ end
@@ -0,0 +1,32 @@
1
+ - XML::XXPath: generalize foo[@x='bar'] to foo[<any XPath
2
+ expression>='bar'] (unless create/create_new implementation proves
3
+ to be too difficult, but I don't think it will...)
4
+
5
+ - documentation:
6
+
7
+ - README:
8
+
9
+ - multi-attribute nodes
10
+
11
+ - XML::Mapping: Move @options hash functionality from
12
+ SingleAttributeNode to Node.
13
+
14
+ - XML::Mapping/default attribute values: Update documentation, digest
15
+ "nil" issues...
16
+
17
+ - add streaming input/output to XML::Mapping, i.e. SAX-based input in
18
+ addition to the current REXML/DOM - based one. Probably won't be
19
+ implementable for some more complicated XPaths -- raise meaningful
20
+ exceptions in those cases.
21
+
22
+ - XML::XXPath/XML::Mapping: add XML text nodes (the sub-node of an
23
+ element node that contains that element's text) first-class to
24
+ XML::XXPath. Use it for things like text_node :contents, "text()".
25
+
26
+ Along those lines: promote XPath node "unspecifiedness" from an
27
+ attribute to a REXML node object of "unspecified" class that's
28
+ turned into an attribute/element/text node when necessary
29
+
30
+ - (eventually, maybe) provide a "scaffolding" feature to automatically
31
+ turn a dtd/schema into a set of node type definitions or even a set
32
+ of mapping classes
@@ -0,0 +1,119 @@
1
+ === latest design (12/2004)
2
+
3
+ At the lowest level, the "Accessors" sub-module contains reader and
4
+ creator functions that correspond to the various types of path
5
+ elements (_elt_name_, @_attr_name_,
6
+ _elt_name_[@_attr_name_='_attr_value_'] etc.) that xml-xxpath
7
+ supports. A reader function gets an array of nodes and the search
8
+ parameters corresponding to its path element type (e.g. _elt_name_,
9
+ _attr_name_, _attr_value_) and returns an array with all matching
10
+ direct sub-nodes of any of the supplied nodes. A creator function gets
11
+ one node and the search parameters and returns the created sub-node.
12
+
13
+ An XPath expression <tt><things1>/<things2>/.../<thingsx></tt> is
14
+ compiled into a bunch of nested closures, each of which is responsible
15
+ for a specific path element and calls the corresponding accessor
16
+ function:
17
+
18
+ - <tt>@creator_procs</tt> -- an array of "creator"
19
+ functions. <tt>@creator_procs[i]</tt> gets passed a base node (XML
20
+ element) and a create_new flag, and it creates the path
21
+ <tt><things[x-i+1]>/<things[x-i+2]>/.../<thingsx></tt> inside the
22
+ base node and returns the hindmost element created (i.e. the one
23
+ corresponding to <tt><thingsx></tt>).
24
+
25
+ - <tt>@reader_proc</tt> -- a "reader" function that gets passed an
26
+ array of nodes and returns an array of all nodes that matched the
27
+ path in any of the supplied nodes, or, if no match was found, throws
28
+ :not_found along with the last non-empty set of nodes that was
29
+ found, and the element of <tt>@creator_procs</tt> that could be used
30
+ to create the remaining part of the path.
31
+
32
+ The +all+ function is then trivially implemented on top of this:
33
+
34
+ def all(node,options={})
35
+ raise "options not a hash" unless Hash===options
36
+ if options[:create_new]
37
+ return [ @creator_procs[-1].call(node,true) ]
38
+ else
39
+ last_nodes,rest_creator = catch(:not_found) do
40
+ return @reader_proc.call([node])
41
+ end
42
+ if options[:ensure_created]
43
+ [ rest_creator.call(last_nodes[0],false) ]
44
+ else
45
+ []
46
+ end
47
+ end
48
+ end
49
+
50
+ ...and +first+, <tt>create_new</tt> etc. are even more trivial
51
+ frontends to that.
52
+
53
+ The implementations of the <tt>@creator_procs</tt> look like this:
54
+
55
+ @creator_procs[0] =
56
+ proc{|node,create_new| node}
57
+
58
+ @creator_procs[1] =
59
+ proc {|node,create_new|
60
+ @creator_procs[0].call(Accessors.create_subnode_by_<thingsx>(node,create_new,<thingsx>),
61
+ create_new)
62
+ }
63
+
64
+ @creator_procs[2] =
65
+ proc {|node,create_new|
66
+ @creator_procs[1].call(Accessors.create_subnode_by_<thingsx-1>(node,create_new,<thingsx-1>),
67
+ create_new)
68
+ }
69
+
70
+ ...
71
+
72
+ @creator_procs[n] =
73
+ proc {|node,create_new|
74
+ @creator_procs[n-1].call(Accessors.create_subnode_by_<things[x+1-n]>(node,create_new,<things[x+1-n]>),
75
+ create_new)
76
+ }
77
+
78
+ ...
79
+ @creator_procs[x] =
80
+ proc {|node,create_new|
81
+ @creator_procs[x-1].call(Accessors.create_subnode_by_<things1>(node,create_new,<things1>),
82
+ create_new)
83
+ }
84
+
85
+
86
+
87
+ ..and the implementation of @reader_proc looks like this:
88
+
89
+ @reader_proc = rpx where
90
+
91
+ rp0 = proc {|nodes| nodes}
92
+
93
+ rp1 = proc {|nodes|
94
+ next_nodes = Accessors.subnodes_by_<thingsx>(nodes,<thingsx>)
95
+ if (next_nodes == [])
96
+ throw :not_found, [nodes,@creator_procs[1]]
97
+ else
98
+ rp0.call(next_nodes)
99
+ end
100
+ }
101
+
102
+ rp2 = proc {|nodes|
103
+ next_nodes = Accessors.subnodes_by_<thingsx-1>(nodes,<thingsx-1>)
104
+ if (next_nodes == [])
105
+ throw :not_found, [nodes,@creator_procs[2]]
106
+ else
107
+ rp1.call(next_nodes)
108
+ end
109
+ }
110
+ ...
111
+
112
+ rpx = proc {|nodes|
113
+ next_nodes = Accessors.subnodes_by_<things1>(nodes,<things1>)
114
+ if (next_nodes == [])
115
+ throw :not_found, [nodes,@creator_procs[x]]
116
+ else
117
+ rpx-1.call(next_nodes)
118
+ end
119
+ }