pdf-labels 1.0.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.
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
+ }