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.
- data/ChangeLog +64 -3
- data/README +871 -173
- data/README_XPATH +40 -13
- data/Rakefile +37 -26
- data/TODO.txt +39 -8
- data/examples/README +5 -0
- data/examples/company_usage.intout +34 -22
- data/examples/documents_folders.rb +31 -0
- data/examples/documents_folders.xml +16 -0
- data/examples/documents_folders_usage.intin.rb +18 -0
- data/examples/documents_folders_usage.intout +46 -0
- data/examples/order_signature_enhanced_usage.intout +21 -11
- data/examples/order_usage.intin.rb +52 -5
- data/examples/order_usage.intout +154 -80
- data/examples/person.intin.rb +44 -0
- data/examples/person.intout +27 -0
- data/examples/person_mm.intin.rb +119 -0
- data/examples/person_mm.intout +114 -0
- data/examples/publication.intin.rb +44 -0
- data/examples/publication.intout +20 -0
- data/examples/reader.intin.rb +33 -0
- data/examples/reader.intout +19 -0
- data/examples/stringarray.rb +5 -0
- data/examples/stringarray.xml +10 -0
- data/examples/stringarray_usage.intin.rb +11 -0
- data/examples/stringarray_usage.intout +31 -0
- data/examples/time_augm.intout +19 -7
- data/examples/time_augm_loading.intin.rb +44 -0
- data/examples/time_augm_loading.intout +12 -0
- data/examples/time_node.intin.rb +79 -0
- data/examples/time_node.rb +3 -2
- data/examples/time_node_w_marshallers.intin.rb +48 -0
- data/examples/time_node_w_marshallers.intout +25 -0
- data/examples/time_node_w_marshallers.xml +9 -0
- data/examples/xpath_create_new.intout +132 -114
- data/examples/xpath_ensure_created.intout +86 -65
- data/examples/xpath_pathological.intout +16 -16
- data/examples/xpath_usage.intout +1 -1
- data/install.rb +1 -0
- data/lib/xml/mapping.rb +3 -1
- data/lib/xml/mapping/base.rb +442 -272
- data/lib/xml/mapping/core_classes_mapping.rb +32 -0
- data/lib/xml/mapping/standard_nodes.rb +176 -86
- data/lib/xml/mapping/version.rb +2 -2
- data/lib/xml/rexml_ext.rb +186 -0
- data/lib/xml/xxpath.rb +28 -265
- data/lib/xml/xxpath/steps.rb +345 -0
- data/lib/xml/xxpath_methods.rb +96 -0
- data/test/all_tests.rb +4 -1
- data/test/benchmark_fixtures.rb +14 -0
- data/test/{multiple_mappings.rb → bookmarks.rb} +0 -0
- data/test/company.rb +47 -0
- data/test/documents_folders.rb +11 -1
- data/test/examples_test.rb +29 -0
- data/test/fixtures/benchmark.xml +77 -0
- data/test/fixtures/company1.xml +9 -0
- data/test/fixtures/documents_folders.xml +0 -8
- data/test/fixtures/documents_folders2.xml +13 -19
- data/test/fixtures/triangle_m1.xml +17 -0
- data/test/fixtures/triangle_m2.xml +19 -0
- data/test/inheritance_test.rb +50 -0
- data/test/multiple_mappings_test.rb +155 -0
- data/test/rexml_xpath_benchmark.rb +29 -0
- data/test/triangle_mm.rb +57 -0
- data/test/xml_mapping_adv_test.rb +36 -1
- data/test/xml_mapping_test.rb +136 -7
- data/test/xpath_test.rb +154 -0
- data/test/xxpath_benchmark.rb +36 -0
- data/test/xxpath_benchmark.result1.txt +17 -0
- data/test/xxpath_methods_test.rb +61 -0
- 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
|
data/test/all_tests.rb
CHANGED
@@ -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
|
File without changes
|
data/test/company.rb
CHANGED
@@ -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
|
data/test/documents_folders.rb
CHANGED
@@ -23,7 +23,17 @@ end
|
|
23
23
|
class Folder <Entry
|
24
24
|
include XML::Mapping
|
25
25
|
|
26
|
-
array_node :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>
|
data/test/fixtures/company1.xml
CHANGED
@@ -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
|
-
<
|
7
|
-
<
|
8
|
-
|
9
|
-
|
10
|
-
</document>
|
6
|
+
<document>
|
7
|
+
<name>plan</name>
|
8
|
+
<contents> inhale, exhale</contents>
|
9
|
+
</document>
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
<folder>
|
12
|
+
<name>work</name>
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
<name>xml-mapping</name>
|
14
|
+
<folder>
|
15
|
+
<name>xml-mapping</name>
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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,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>
|