xml-mapping 0.8.1 → 0.9.1

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 (71) hide show
  1. data/ChangeLog +64 -3
  2. data/README +871 -173
  3. data/README_XPATH +40 -13
  4. data/Rakefile +37 -26
  5. data/TODO.txt +39 -8
  6. data/examples/README +5 -0
  7. data/examples/company_usage.intout +34 -22
  8. data/examples/documents_folders.rb +31 -0
  9. data/examples/documents_folders.xml +16 -0
  10. data/examples/documents_folders_usage.intin.rb +18 -0
  11. data/examples/documents_folders_usage.intout +46 -0
  12. data/examples/order_signature_enhanced_usage.intout +21 -11
  13. data/examples/order_usage.intin.rb +52 -5
  14. data/examples/order_usage.intout +154 -80
  15. data/examples/person.intin.rb +44 -0
  16. data/examples/person.intout +27 -0
  17. data/examples/person_mm.intin.rb +119 -0
  18. data/examples/person_mm.intout +114 -0
  19. data/examples/publication.intin.rb +44 -0
  20. data/examples/publication.intout +20 -0
  21. data/examples/reader.intin.rb +33 -0
  22. data/examples/reader.intout +19 -0
  23. data/examples/stringarray.rb +5 -0
  24. data/examples/stringarray.xml +10 -0
  25. data/examples/stringarray_usage.intin.rb +11 -0
  26. data/examples/stringarray_usage.intout +31 -0
  27. data/examples/time_augm.intout +19 -7
  28. data/examples/time_augm_loading.intin.rb +44 -0
  29. data/examples/time_augm_loading.intout +12 -0
  30. data/examples/time_node.intin.rb +79 -0
  31. data/examples/time_node.rb +3 -2
  32. data/examples/time_node_w_marshallers.intin.rb +48 -0
  33. data/examples/time_node_w_marshallers.intout +25 -0
  34. data/examples/time_node_w_marshallers.xml +9 -0
  35. data/examples/xpath_create_new.intout +132 -114
  36. data/examples/xpath_ensure_created.intout +86 -65
  37. data/examples/xpath_pathological.intout +16 -16
  38. data/examples/xpath_usage.intout +1 -1
  39. data/install.rb +1 -0
  40. data/lib/xml/mapping.rb +3 -1
  41. data/lib/xml/mapping/base.rb +442 -272
  42. data/lib/xml/mapping/core_classes_mapping.rb +32 -0
  43. data/lib/xml/mapping/standard_nodes.rb +176 -86
  44. data/lib/xml/mapping/version.rb +2 -2
  45. data/lib/xml/rexml_ext.rb +186 -0
  46. data/lib/xml/xxpath.rb +28 -265
  47. data/lib/xml/xxpath/steps.rb +345 -0
  48. data/lib/xml/xxpath_methods.rb +96 -0
  49. data/test/all_tests.rb +4 -1
  50. data/test/benchmark_fixtures.rb +14 -0
  51. data/test/{multiple_mappings.rb → bookmarks.rb} +0 -0
  52. data/test/company.rb +47 -0
  53. data/test/documents_folders.rb +11 -1
  54. data/test/examples_test.rb +29 -0
  55. data/test/fixtures/benchmark.xml +77 -0
  56. data/test/fixtures/company1.xml +9 -0
  57. data/test/fixtures/documents_folders.xml +0 -8
  58. data/test/fixtures/documents_folders2.xml +13 -19
  59. data/test/fixtures/triangle_m1.xml +17 -0
  60. data/test/fixtures/triangle_m2.xml +19 -0
  61. data/test/inheritance_test.rb +50 -0
  62. data/test/multiple_mappings_test.rb +155 -0
  63. data/test/rexml_xpath_benchmark.rb +29 -0
  64. data/test/triangle_mm.rb +57 -0
  65. data/test/xml_mapping_adv_test.rb +36 -1
  66. data/test/xml_mapping_test.rb +136 -7
  67. data/test/xpath_test.rb +154 -0
  68. data/test/xxpath_benchmark.rb +36 -0
  69. data/test/xxpath_benchmark.result1.txt +17 -0
  70. data/test/xxpath_methods_test.rb +61 -0
  71. metadata +139 -90
@@ -0,0 +1,96 @@
1
+ # xxpath -- XPath implementation for Ruby, including write access
2
+ # Copyright (C) 2004-2010 Olaf Klischat
3
+
4
+ require File.dirname(__FILE__) + "/xxpath"
5
+
6
+ module XML
7
+
8
+ # set of convenience wrappers around XML::XPath's instance methods,
9
+ # for people who frequently use XML::XPath directly. This module is
10
+ # included into the REXML node classes and adds methods to them that
11
+ # enable you to write a call like
12
+ #
13
+ # path.first(xml_element)
14
+ #
15
+ # as the more pleasant-looking variant
16
+ #
17
+ # xml_element.first_xpath(path)
18
+ #
19
+ # with the added bonus that _path_ may not only be an XML::XXPath
20
+ # instance, but also just a String containing the XPath expression.
21
+ #
22
+ # Please note that the names of all the added methods are suffixed
23
+ # with "_xpath" to avoid name clashes with REXML methods. Please
24
+ # note also that this was changed recently, so older versions of
25
+ # xml-mapping (version < 0.9) used method names without _xpath
26
+ # appended and thus would be incompatible with this one here.
27
+ #
28
+ # As a special convenience, if you're using an older version of
29
+ # REXML that doesn't have the new methods yet, methods without
30
+ # _xpath in their names will also (additionally) be added to the
31
+ # REXML classes. This will enable code that relied on the old names
32
+ # to keep on working as long as REXML isn't updated, at which point
33
+ # that code will fail and must be changed to used the methods
34
+ # suffixed with _xpath.
35
+ module XXPathMethods
36
+ # see XML::XXPath#each
37
+ def each_xpath(path,options={},&block)
38
+ to_xxpath(path).each self, options, &block
39
+ end
40
+
41
+ # see XML::XXPath#first
42
+ def first_xpath(path,options={})
43
+ to_xxpath(path).first self, options
44
+ end
45
+
46
+ # see XML::XXPath#all
47
+ def all_xpath(path,options={})
48
+ to_xxpath(path).all self, options
49
+ end
50
+
51
+ # see XML::XXPath#create_new
52
+ def create_new_xpath(path)
53
+ to_xxpath(path).create_new self
54
+ end
55
+
56
+ unless REXML::Element.new.respond_to? :first
57
+
58
+ # see XML::XXPath#first
59
+ def first_xpath(path,options={})
60
+ to_xxpath(path).first self, options
61
+ end
62
+
63
+ # see XML::XXPath#all
64
+ def all_xpath(path,options={})
65
+ to_xxpath(path).all self, options
66
+ end
67
+
68
+ # see XML::XXPath#create_new
69
+ def create_new_xpath(path)
70
+ to_xxpath(path).create_new self
71
+ end
72
+
73
+ end
74
+
75
+ def to_xxpath(path)
76
+ if String===path
77
+ XXPath.new path
78
+ else
79
+ path
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+
87
+ module REXML
88
+ class Child # mix into nearly every REXML class -- maybe this is a bit too brutal
89
+ include XML::XXPathMethods
90
+ end
91
+ end
92
+
93
+
94
+ class XML::XXPath::Accessors::Attribute
95
+ include XML::XXPathMethods
96
+ end
@@ -3,4 +3,7 @@ require File.dirname(__FILE__)+"/tests_init"
3
3
  require 'xpath_test'
4
4
  require 'xml_mapping_test'
5
5
  require 'xml_mapping_adv_test'
6
-
6
+ require 'multiple_mappings_test'
7
+ require 'xxpath_methods_test'
8
+ require 'examples_test'
9
+ require 'inheritance_test'
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__)+"/tests_init"
2
+
3
+ require "rexml/document"
4
+ include REXML
5
+
6
+ @d = Document.new(File.new(File.dirname(__FILE__) + "/fixtures/benchmark.xml"))
7
+
8
+ @path_by_name = "foo/bar/foo/bar"
9
+ @path_by_idx = "foo/bar[5]" # "bar6"
10
+ @path_by_idx_idx = "foo/bar[3]/bar[4]" # "bar4-6"
11
+ @path_by_attr_idx = "foo/bar[@barkey='subtree']/bar[4]" # "bar4-6"
12
+ @path_by_attr = "@key" # "xy"
13
+
14
+ @count=500
@@ -4,6 +4,7 @@ require 'xml/mapping'
4
4
  class Address; end
5
5
  class Office; end
6
6
  class Customer; end
7
+ class Thing; end
7
8
 
8
9
 
9
10
  class Company
@@ -21,6 +22,7 @@ class Company
21
22
  text_node :ent3, "arrtest/entry[3]"
22
23
 
23
24
  array_node :stuff, "stuff", "*"
25
+ array_node :things, "stuff2", "thing", :class=>Thing
24
26
 
25
27
  object_node :test_default_value_identity, "dummy", :default_value => ["default"]
26
28
  end
@@ -54,3 +56,48 @@ class Customer
54
56
  text_node :uid, "@uid"
55
57
  text_node :name, "name"
56
58
  end
59
+
60
+
61
+ class Thing
62
+ include XML::Mapping
63
+
64
+ choice_node 'name', (text_node :name, 'name'),
65
+ '@name', (text_node :name, '@name'),
66
+ :else, (text_node :name, '.')
67
+ end
68
+
69
+
70
+ class Names1
71
+ include XML::Mapping
72
+
73
+ choice_node :if, 'name', :then, (text_node :name, 'name'),
74
+ :elsif, 'names/name', :then, (array_node :names, 'names', 'name', :class=>String)
75
+ end
76
+
77
+
78
+ class ReaderTest
79
+ include XML::Mapping
80
+
81
+ attr_accessor :read
82
+
83
+ text_node :foo, "foo"
84
+ text_node :foo2, "foo2", :reader=>proc{|obj,xml| (obj.read||=[]) << :foo2 }
85
+ text_node :foo3, "foo3", :reader=>proc{|obj,xml,default|
86
+ (obj.read||=[]) << :foo3
87
+ default.call(obj,xml)
88
+ }
89
+ text_node :bar, "bar"
90
+ end
91
+
92
+
93
+ class WriterTest
94
+ include XML::Mapping
95
+
96
+ text_node :foo, "foo"
97
+ text_node :foo2, "foo2", :writer=>proc{|obj,xml| e = xml.elements.add; e.name='quux'; e.text='dingdong2' }
98
+ text_node :foo3, "foo3", :writer=>proc{|obj,xml,default|
99
+ default.call(obj,xml)
100
+ e = xml.elements.add; e.name='quux'; e.text='dingdong3'
101
+ }
102
+ text_node :bar, "bar"
103
+ end
@@ -23,7 +23,17 @@ end
23
23
  class Folder <Entry
24
24
  include XML::Mapping
25
25
 
26
- array_node :entries, "entries", "*"
26
+ array_node :entries, "document|folder", :default_value=>[]
27
+
28
+ def [](name)
29
+ entries.select{|e|e.name==name}[0]
30
+ end
31
+
32
+ def append(name,entry)
33
+ entries << entry
34
+ entry.name = name
35
+ entry
36
+ end
27
37
 
28
38
  def ==(other)
29
39
  Folder===other and
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__)+"/tests_init"
2
+ $:.unshift File.dirname(__FILE__)+"/../examples"
3
+
4
+ require 'test/unit'
5
+ require 'xml/xxpath_methods'
6
+
7
+ require 'xml/mapping'
8
+
9
+ # unit tests for some code in ../examples. Most of that code is
10
+ # included in ../README and tested when regenerating the README, but
11
+ # some things are better done outside.
12
+ class ExamplesTest < Test::Unit::TestCase
13
+
14
+ def test_time_node
15
+ require 'time_node'
16
+ require 'order_signature_enhanced'
17
+
18
+ s = Signature.load_from_file File.dirname(__FILE__)+"/../examples/order_signature_enhanced.xml"
19
+ assert_equal Time.local(2005,2,13), s.signed_on
20
+
21
+ s.signed_on = Time.local(2006,6,15)
22
+ xml2 = s.save_to_xml
23
+
24
+ assert_equal "15", xml2.first_xpath("signed-on/day").text
25
+ assert_equal "6", xml2.first_xpath("signed-on/month").text
26
+ assert_equal "2006", xml2.first_xpath("signed-on/year").text
27
+ end
28
+
29
+ end
@@ -0,0 +1,77 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <bla rootkey='rootkeyval'>
4
+ <foo>x</foo>
5
+ <bar>bar1</bar>
6
+ <foo key='xy'>
7
+ y
8
+ <u/>
9
+ <bar barkey='hello'>
10
+ bar2
11
+ </bar>
12
+ <quux barkey='goodbye'>
13
+ quux1
14
+ </quux>
15
+ <bar>
16
+ bar3
17
+ </bar>
18
+ <bar barkey='subtree'>
19
+ bar4
20
+ <bar>
21
+ bar4-1
22
+ </bar>
23
+ <foo>
24
+ z
25
+ <bar>
26
+ bar4-2
27
+ </bar>
28
+ hello
29
+ <bar>
30
+ bar4-3
31
+ </bar>
32
+ </foo>
33
+ <bar>
34
+ bar4-4
35
+ </bar>
36
+ <bar>
37
+ bar4-5
38
+ </bar>
39
+ <quux barkey='hello'>
40
+ bar4-quux1
41
+ </quux>
42
+ <bar>
43
+ bar4-6
44
+ </bar>
45
+ <bar>
46
+ bar4-7
47
+ </bar>
48
+ </bar>
49
+ <quux barkey='hello'>
50
+ quux2
51
+ </quux>
52
+ This buffer is for notes you don't want to save, and for Lisp
53
+ evaluation. If you want to create a file, first visit that file
54
+ with C-x C-f, then enter the text in that file's own buffer.
55
+ <bar>
56
+ bar5
57
+ </bar>
58
+ <bar>
59
+ bar6
60
+ </bar>
61
+ <quux>
62
+ quux3
63
+ </quux>
64
+ <quux barkey='hello'>
65
+ quux4
66
+ </quux>
67
+ <bar>
68
+ bar7
69
+ </bar>
70
+ <bar>
71
+ bar8
72
+ </bar>
73
+ <bar>
74
+ bar9
75
+ </bar>
76
+ </foo>
77
+ </bla>
@@ -82,4 +82,13 @@
82
82
  </address>
83
83
  </office>
84
84
  </stuff>
85
+
86
+ <stuff2>
87
+ <thing name="name1"/>
88
+ <thing>
89
+ <name>name2</name>
90
+ </thing>
91
+ <thing>name3</thing>
92
+ <thing name="name4-attr">name4-inline<name>name4-elt</name></thing>
93
+ </stuff2>
85
94
  </company>
@@ -4,7 +4,6 @@
4
4
  <folder>
5
5
  <name>home</name>
6
6
 
7
- <entries>
8
7
  <document>
9
8
  <name>plan</name>
10
9
  <contents>
@@ -16,11 +15,9 @@
16
15
  <folder>
17
16
  <name>work</name>
18
17
 
19
- <entries>
20
18
  <folder>
21
19
  <name>xml-mapping</name>
22
20
 
23
- <entries>
24
21
  <document>
25
22
  <name>README</name>
26
23
  <contents>
@@ -34,7 +31,6 @@
34
31
  rake away
35
32
  </contents>
36
33
  </document>
37
- </entries>
38
34
  </folder>
39
35
 
40
36
  <document>
@@ -44,14 +40,12 @@
44
40
  4:00 PM appointment
45
41
  </contents>
46
42
  </document>
47
- </entries>
48
43
  </folder>
49
44
 
50
45
 
51
46
  <folder>
52
47
  <name>books</name>
53
48
 
54
- <entries>
55
49
  <document>
56
50
  <name>The Hitchhiker's Guide to the Galaxy</name>
57
51
  <contents>
@@ -64,8 +58,6 @@
64
58
  The Pragmatic Programmer's Guide
65
59
  </contents>
66
60
  </document>
67
- </entries>
68
61
  </folder>
69
62
 
70
- </entries>
71
63
  </folder>
@@ -3,28 +3,22 @@
3
3
  <folder>
4
4
  <name>home</name>
5
5
 
6
- <entries>
7
- <document>
8
- <name>plan</name>
9
- <contents> inhale, exhale</contents>
10
- </document>
6
+ <document>
7
+ <name>plan</name>
8
+ <contents> inhale, exhale</contents>
9
+ </document>
11
10
 
12
- <folder>
13
- <name>work</name>
11
+ <folder>
12
+ <name>work</name>
14
13
 
15
- <entries>
16
- <folder>
17
- <name>xml-mapping</name>
14
+ <folder>
15
+ <name>xml-mapping</name>
18
16
 
19
- <entries>
20
- <document>
21
- <name>README</name>
22
- <contents>foo bar baz</contents>
23
- </document>
24
- </entries>
25
- </folder>
26
- </entries>
17
+ <document>
18
+ <name>README</name>
19
+ <contents>foo bar baz</contents>
20
+ </document>
27
21
  </folder>
22
+ </folder>
28
23
 
29
- </entries>
30
24
  </folder>
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <triangle name="tri1" >
4
+ <pt1>
5
+ <x> 3 </x>
6
+ <y> 0 </y>
7
+ </pt1>
8
+ <pt2>
9
+ <x> 2 </x>
10
+ <y> 4 </y>
11
+ </pt2>
12
+ <pt3>
13
+ <x> 0 </x>
14
+ <y> 1 </y>
15
+ </pt3>
16
+ <color>green</color>
17
+ </triangle>
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <triangle color="green">
4
+ <name>tri1</name>
5
+ <points>
6
+ <point>
7
+ <x> 3 </x>
8
+ <y> 0 </y>
9
+ </point>
10
+ <point>
11
+ <x> 2 </x>
12
+ <y> 4 </y>
13
+ </point>
14
+ <point>
15
+ <x> 0 </x>
16
+ <y> 1 </y>
17
+ </point>
18
+ </points>
19
+ </triangle>