xml-mapping 0.8.1 → 0.9.1

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