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.
- 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
data/README_XPATH
CHANGED
@@ -8,12 +8,18 @@ uses xml-xxpath extensively for implementing its node types -- see the
|
|
8
8
|
README file and the reference documentation (and the source code) for
|
9
9
|
details. xml-xxpath, however, does not depend on xml-mapping at all,
|
10
10
|
and is useful in its own right -- maybe I'll later distribute it as a
|
11
|
-
seperate library instead of bundling it.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
seperate library instead of bundling it. For the time being, if you
|
12
|
+
want to use this XPath implementation stand-alone, you can just rip
|
13
|
+
the files <tt>lib/xml/xxpath.rb</tt>,
|
14
|
+
<tt>lib/xml/xxpath/steps.rb</tt>, and
|
15
|
+
<tt>lib/xml/xxpath_methods.rb</tt> out of the xml-mapping distribution
|
16
|
+
and use them on their own (they do not depend on anything else).
|
17
|
+
|
18
|
+
xml-xxpath's XPath support is vastly incomplete (see below), but, in
|
19
|
+
addition to the normal reading/matching functionality found in other
|
20
|
+
XPath implementations (i.e. "find all elements in a given XML document
|
21
|
+
matching a given XPath expression"), xml-xxpath supports <i>write
|
22
|
+
access</i>. For example, when writing the XPath expression
|
17
23
|
"/foo/bar[3]/baz[@key='hiho']" to the XML document
|
18
24
|
|
19
25
|
<foo>
|
@@ -40,14 +46,13 @@ of the existing XPath implementations, e.g. the one that comes with
|
|
40
46
|
REXML. Also, the whole xml-xxpath implementation is just 300 lines of
|
41
47
|
Ruby code, it is quite fast (paths are precompiled), and xml-xxpath
|
42
48
|
returns matched elements in the order they appeared in the source
|
43
|
-
document -- I've heard REXML::
|
49
|
+
document -- I've heard REXML::XPath doesn't do that :)
|
44
50
|
|
45
|
-
Some basic knowledge of XPath is helpful for reading this document
|
46
|
-
don't know very much either).
|
51
|
+
Some basic knowledge of XPath is helpful for reading this document.
|
47
52
|
|
48
53
|
At the moment, xml-xxpath understands XPath expressions of the form
|
49
|
-
[<tt>/</tt>]_pathelement_<tt
|
50
|
-
each _pathelement_ must be one of these:
|
54
|
+
[<tt>/</tt>]_pathelement_<tt>/[/]</tt>_pathelement_<tt>/[/]</tt>...,
|
55
|
+
where each _pathelement_ must be one of these:
|
51
56
|
|
52
57
|
- a simple element name _name_, e.g. +signature+
|
53
58
|
|
@@ -60,6 +65,23 @@ each _pathelement_ must be one of these:
|
|
60
65
|
|
61
66
|
- the "match-all" path element, <tt>*</tt>
|
62
67
|
|
68
|
+
- .
|
69
|
+
|
70
|
+
- name1|name2|...
|
71
|
+
|
72
|
+
- .[@key='xy'] / self::*[@key='xy']
|
73
|
+
|
74
|
+
- child::*[@key='xy']
|
75
|
+
|
76
|
+
- text()
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
Xml-xxpath only supports relative paths at this time, i.e. XPath
|
81
|
+
expressions beginning with "/" or "//" will still only find nodes
|
82
|
+
below the node the expression is applied to (as if you had written
|
83
|
+
"./" or ".//", respectively).
|
84
|
+
|
63
85
|
|
64
86
|
== Usage
|
65
87
|
|
@@ -115,7 +137,7 @@ against the +firstelt+ element in the example *must not* start with
|
|
115
137
|
|
116
138
|
=== Write Access
|
117
139
|
|
118
|
-
You may pass
|
140
|
+
You may pass an <tt>:ensure_created=>true</tt> option argument to
|
119
141
|
_path_.first(_elt_)/_path_.all(_elt_) calls to make sure that _path_
|
120
142
|
exists inside the passed XML element _elt_. If it existed before,
|
121
143
|
nothing changes, and the call behaves just as it would without the
|
@@ -141,13 +163,18 @@ Examples:
|
|
141
163
|
Alternatively, you may pass a <tt>:create_new=>true</tt> option
|
142
164
|
argument or call <tt>create_new</tt> (_path_.create_new(_elt_) is
|
143
165
|
equivalent to _path_.first(_elt_,:create_new=>true)). In that case, a
|
144
|
-
new node
|
166
|
+
new node is created in _elt_ for each path element of _path_ (or an
|
145
167
|
exception raised if that wasn't possible for any path element).
|
146
168
|
|
147
169
|
Examples:
|
148
170
|
|
149
171
|
:include: xpath_create_new.intout
|
150
172
|
|
173
|
+
This feature is used in xml-mapping by node types like
|
174
|
+
XML::Mapping::ArrayNode, which must create a new instance of the
|
175
|
+
"per-array element path" for each element of the array to be stored in
|
176
|
+
an XML tree.
|
177
|
+
|
151
178
|
|
152
179
|
=== Pathological Cases
|
153
180
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
# adapted from active_record's Rakefile
|
3
3
|
|
4
|
+
require 'build_lib/rdoc_ext'
|
5
|
+
|
4
6
|
require 'rubygems'
|
5
7
|
require 'rake'
|
6
8
|
require 'rake/testtask'
|
7
|
-
require '
|
9
|
+
require 'build_lib/my_rdoctask'
|
8
10
|
require 'rake/packagetask'
|
9
11
|
require 'rake/gempackagetask'
|
10
12
|
#require 'rake/contrib/rubyforgepublisher'
|
@@ -12,13 +14,8 @@ require 'rake/contrib/sshpublisher'
|
|
12
14
|
|
13
15
|
require File.dirname(__FILE__)+"/lib/xml/mapping/version"
|
14
16
|
|
15
|
-
|
16
17
|
# yeah -- it's just stupid that these are private
|
17
18
|
|
18
|
-
class Rake::RDocTask
|
19
|
-
public :rdoc_target
|
20
|
-
end
|
21
|
-
|
22
19
|
class Rake::PackageTask
|
23
20
|
public :tgz_file, :zip_file
|
24
21
|
end
|
@@ -28,18 +25,33 @@ class Rake::GemPackageTask
|
|
28
25
|
end
|
29
26
|
|
30
27
|
|
31
|
-
FILES_RDOC_EXTRA=%w{README README_XPATH TODO.txt doc/xpath_impl_notes.txt}
|
28
|
+
FILES_RDOC_EXTRA=%w{README README_XPATH ChangeLog TODO.txt doc/xpath_impl_notes.txt}
|
32
29
|
FILES_RDOC_INCLUDES=%w{examples/company.xml
|
33
30
|
examples/company.rb
|
34
31
|
examples/company_usage.intout
|
32
|
+
examples/order.xml
|
33
|
+
examples/order.rb
|
35
34
|
examples/order_usage.intout
|
35
|
+
examples/stringarray_usage.intout
|
36
|
+
examples/stringarray.xml
|
37
|
+
examples/documents_folders_usage.intout
|
38
|
+
examples/documents_folders.xml
|
39
|
+
examples/time_node_w_marshallers.intout
|
40
|
+
examples/time_node_w_marshallers.xml
|
36
41
|
examples/time_augm.intout
|
42
|
+
examples/time_augm_loading.intout
|
37
43
|
examples/xpath_usage.intout
|
38
44
|
examples/xpath_ensure_created.intout
|
39
45
|
examples/xpath_create_new.intout
|
40
46
|
examples/xpath_pathological.intout
|
41
47
|
examples/xpath_docvsroot.intout
|
42
|
-
examples/order_signature_enhanced_usage.intout
|
48
|
+
examples/order_signature_enhanced_usage.intout
|
49
|
+
examples/order_signature_enhanced.xml
|
50
|
+
examples/person.intout
|
51
|
+
examples/publication.intout
|
52
|
+
examples/reader.intout
|
53
|
+
examples/person_mm.intout
|
54
|
+
}
|
43
55
|
|
44
56
|
|
45
57
|
desc "Default Task"
|
@@ -48,6 +60,7 @@ task :default => [ :test ]
|
|
48
60
|
Rake::TestTask.new(:test) { |t|
|
49
61
|
t.test_files = ["test/all_tests.rb"]
|
50
62
|
t.verbose = true
|
63
|
+
# t.loader = :testrb
|
51
64
|
}
|
52
65
|
|
53
66
|
# runs tests only if sources have changed since last succesful run of
|
@@ -59,10 +72,10 @@ end
|
|
59
72
|
|
60
73
|
|
61
74
|
|
62
|
-
|
75
|
+
MyRDocTask.new { |rdoc|
|
63
76
|
rdoc.rdoc_dir = 'doc/api'
|
64
77
|
rdoc.title = "XML::Mapping -- Simple, extensible Ruby-to-XML (and back) mapper"
|
65
|
-
rdoc.options
|
78
|
+
rdoc.options += %w{--line-numbers --inline-source --accessor cattr_accessor=object --include examples}
|
66
79
|
rdoc.rdoc_files.include(*FILES_RDOC_EXTRA)
|
67
80
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
68
81
|
|
@@ -139,20 +152,17 @@ end
|
|
139
152
|
|
140
153
|
# have to add additional prerequisites manually because it appears
|
141
154
|
# that rules can only define a single prerequisite :-\
|
142
|
-
|
143
|
-
|
144
|
-
|
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")
|
155
|
+
FILES_RDOC_INCLUDES.select{|f|f=~/.intout$/}.each do |f|
|
156
|
+
file f => FileList.new("lib/**/*.rb")
|
157
|
+
file f => FileList.new("examples/**/*.rb")
|
154
158
|
end
|
155
159
|
|
160
|
+
file 'examples/company_usage.intout' => ['examples/company.xml']
|
161
|
+
file 'examples/documents_folders_usage.intout' => ['examples/documents_folders.xml']
|
162
|
+
file 'examples/order_signature_enhanced_usage.intout' => ['examples/order_signature_enhanced.xml']
|
163
|
+
file 'examples/order_usage.intout' => ['examples/order.xml']
|
164
|
+
file 'examples/stringarray_usage.intout' => ['examples/stringarray.xml']
|
165
|
+
|
156
166
|
|
157
167
|
spec = Gem::Specification.new do |s|
|
158
168
|
s.name = 'xml-mapping'
|
@@ -168,12 +178,12 @@ spec = Gem::Specification.new do |s|
|
|
168
178
|
s.files += Dir.glob("{lib,examples,test}/**/*").delete_if do |item|
|
169
179
|
item.include?("CVS") || item =~ /~$/
|
170
180
|
end
|
171
|
-
s.files += %w{LICENSE Rakefile
|
181
|
+
s.files += %w{LICENSE Rakefile install.rb}
|
172
182
|
s.extra_rdoc_files = FILES_RDOC_EXTRA
|
173
183
|
s.rdoc_options += %w{--include examples}
|
174
184
|
|
175
185
|
s.require_path = 'lib'
|
176
|
-
s.autorequire = 'xml/mapping'
|
186
|
+
# s.autorequire = 'xml/mapping'
|
177
187
|
|
178
188
|
# s.add_dependency 'rexml'
|
179
189
|
|
@@ -182,8 +192,9 @@ spec = Gem::Specification.new do |s|
|
|
182
192
|
s.test_file = 'test/all_tests.rb'
|
183
193
|
|
184
194
|
s.author = 'Olaf Klischat'
|
185
|
-
s.email = 'klischat@
|
195
|
+
s.email = 'olaf.klischat@sofd.de'
|
186
196
|
s.homepage = "http://xml-mapping.rubyforge.org"
|
197
|
+
s.rubyforge_project = "xml-mapping"
|
187
198
|
end
|
188
199
|
|
189
200
|
|
@@ -207,7 +218,7 @@ end
|
|
207
218
|
|
208
219
|
|
209
220
|
task :rfpub_rdoc => [:rdoc] do
|
210
|
-
p=Rake::SshDirPublisher.new('
|
221
|
+
p=Rake::SshDirPublisher.new('rubyforge.org',
|
211
222
|
'/var/www/gforge-projects/xml-mapping/',
|
212
223
|
'doc/api')
|
213
224
|
p.upload
|
data/TODO.txt
CHANGED
@@ -1,18 +1,49 @@
|
|
1
|
-
- XML::XXPath:
|
2
|
-
|
3
|
-
|
1
|
+
- XML::XXPath: Write a real XPath parser eventually
|
2
|
+
|
3
|
+
- XML::XXPath: avoid duplicates in path.all(node) result arrays when
|
4
|
+
using the descendants ("//") axis
|
5
|
+
|
6
|
+
- invent an XPath-like language for Ruby object graphs (i.e. a
|
7
|
+
language that is to Ruby object graphs what XPath is to XML
|
8
|
+
trees). Use expressions in that language as a generalization of
|
9
|
+
"attribute names" (e.g. the 1st parameter to single attribute node
|
10
|
+
factory methods). The language could more or less be Ruby itself,
|
11
|
+
but the write support would need some extra work...
|
12
|
+
|
13
|
+
- XML::XXPath:
|
14
|
+
|
15
|
+
- implement .[@attrname] steps
|
16
|
+
|
17
|
+
- returns the context node iff it contains an attrname attribute
|
18
|
+
|
19
|
+
- doesn't work properly in REXML::XPath?
|
20
|
+
|
21
|
+
- implement *[@attrname] steps
|
22
|
+
|
23
|
+
- implement *[@attrname='attrvalue'] steps
|
24
|
+
|
25
|
+
- id/idref support (write support possible?)
|
26
|
+
|
27
|
+
- XML::Mapping: make SubObjectBaseNode a mixin instead of a subclass
|
28
|
+
of SingleAttributeNode ("mapping sub-objects" and "mapping to a
|
29
|
+
single attribute" are orthogonal concepts; inheritance is bad design
|
30
|
+
here)
|
4
31
|
|
5
32
|
- documentation:
|
6
33
|
|
7
34
|
- README:
|
8
35
|
|
9
|
-
-
|
36
|
+
- document/show usage of default_when_xpath_err outside node type
|
37
|
+
implementations
|
38
|
+
|
39
|
+
- README_XPATH:
|
40
|
+
|
41
|
+
- mention new step types, new axes, xml/xpath_methods
|
10
42
|
|
11
|
-
- XML::Mapping: Move @options hash functionality from
|
12
|
-
SingleAttributeNode to Node.
|
13
43
|
|
14
|
-
- XML::Mapping
|
15
|
-
|
44
|
+
- XML::XXPath/XML::Mapping: support for XML namespaces in XML::XXPath
|
45
|
+
(match nodes with specific namespaces only) and XML::Mapping
|
46
|
+
(use_namespace etc.)
|
16
47
|
|
17
48
|
- add streaming input/output to XML::Mapping, i.e. SAX-based input in
|
18
49
|
addition to the current REXML/DOM - based one. Probably won't be
|
data/examples/README
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
This directory contains the example code snippets from the main README
|
2
|
+
file (each time the documentation is regenerated, they're included in
|
3
|
+
the README, executed, and their output is checked for correctness and
|
4
|
+
included in the README as well). So, if you've read the README, you've
|
5
|
+
already seen all the examples from this directory.
|
@@ -1,11 +1,11 @@
|
|
1
1
|
c = Company.load_from_file('company.xml')
|
2
|
-
=> #<Company:
|
2
|
+
=> #<Company:0x7f487635b068 @address=#<Address:0x7f487635a1e0 @zip=10113, @city="Berlin">, @name="ACME inc.", @customers=[#<Customer:0x7f48763584d0 @name="James Kirk", @id="jim">, #<Customer:0x7f4876356d88 @name="Ernie", @id="ernie">, #<Customer:0x7f4876355640 @name="Bert", @id="bert">]>
|
3
3
|
c.name
|
4
4
|
=> "ACME inc."
|
5
5
|
c.customers.size
|
6
6
|
=> 3
|
7
7
|
c.customers[1]
|
8
|
-
=> #<Customer:
|
8
|
+
=> #<Customer:0x7f4876356d88 @name="Ernie", @id="ernie">
|
9
9
|
c.customers[1].name
|
10
10
|
=> "Ernie"
|
11
11
|
c.customers[0].name
|
@@ -13,27 +13,39 @@ c.customers[0].name
|
|
13
13
|
c.customers[0].name = 'James Tiberius Kirk'
|
14
14
|
=> "James Tiberius Kirk"
|
15
15
|
c.customers << Customer.new('cm','Cookie Monster')
|
16
|
-
=> [#<Customer:
|
16
|
+
=> [#<Customer:0x7f48763584d0 @name="James Tiberius Kirk", @id="jim">, #<Customer:0x7f4876356d88 @name="Ernie", @id="ernie">, #<Customer:0x7f4876355640 @name="Bert", @id="bert">, #<Customer:0x7f4876352b48 @name="Cookie Monster", @id="cm">]
|
17
17
|
xml2 = c.save_to_xml
|
18
18
|
=> <company name='ACME inc.'> ... </>
|
19
19
|
xml2.write($stdout,2)
|
20
20
|
<company name='ACME inc.'>
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
</
|
39
|
-
</
|
21
|
+
<address>
|
22
|
+
<city>
|
23
|
+
Berlin
|
24
|
+
</city>
|
25
|
+
<zip>
|
26
|
+
10113
|
27
|
+
</zip>
|
28
|
+
</address>
|
29
|
+
<customers>
|
30
|
+
<customer id='69974598795880'>
|
31
|
+
<name>
|
32
|
+
James Tiberius Kirk
|
33
|
+
</name>
|
34
|
+
</customer>
|
35
|
+
<customer id='69974598792900'>
|
36
|
+
<name>
|
37
|
+
Ernie
|
38
|
+
</name>
|
39
|
+
</customer>
|
40
|
+
<customer id='69974598789920'>
|
41
|
+
<name>
|
42
|
+
Bert
|
43
|
+
</name>
|
44
|
+
</customer>
|
45
|
+
<customer id='69974598784420'>
|
46
|
+
<name>
|
47
|
+
Cookie Monster
|
48
|
+
</name>
|
49
|
+
</customer>
|
50
|
+
</customers>
|
51
|
+
</company>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'xml/mapping'
|
2
|
+
|
3
|
+
class Entry
|
4
|
+
include XML::Mapping
|
5
|
+
|
6
|
+
text_node :name, "@name"
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
class Document <Entry
|
11
|
+
include XML::Mapping
|
12
|
+
|
13
|
+
text_node :contents, "contents"
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
class Folder <Entry
|
18
|
+
include XML::Mapping
|
19
|
+
|
20
|
+
array_node :entries, "document|folder", :default_value=>[]
|
21
|
+
|
22
|
+
def [](name)
|
23
|
+
entries.select{|e|e.name==name}[0]
|
24
|
+
end
|
25
|
+
|
26
|
+
def append(name,entry)
|
27
|
+
entries << entry
|
28
|
+
entry.name = name
|
29
|
+
entry
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<?xml version="1.0" encoding="ISO-8859-1"?>
|
2
|
+
|
3
|
+
<folder name="home">
|
4
|
+
<document name="plan">
|
5
|
+
<contents> inhale, exhale</contents>
|
6
|
+
</document>
|
7
|
+
|
8
|
+
<folder name="work">
|
9
|
+
<folder name="xml-mapping">
|
10
|
+
<document name="README">
|
11
|
+
<contents>foo bar baz</contents>
|
12
|
+
</document>
|
13
|
+
</folder>
|
14
|
+
</folder>
|
15
|
+
|
16
|
+
</folder>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#:invisible:
|
2
|
+
$:.unshift "../lib"
|
3
|
+
require 'documents_folders' #<=
|
4
|
+
#:visible:
|
5
|
+
|
6
|
+
root = XML::Mapping.load_object_from_file "documents_folders.xml" #<=
|
7
|
+
root.name #<=
|
8
|
+
root.entries #<=
|
9
|
+
|
10
|
+
root.append "etc", Folder.new
|
11
|
+
root["etc"].append "passwd", Document.new
|
12
|
+
root["etc"]["passwd"].contents = "foo:x:2:2:/bin/sh"
|
13
|
+
root["etc"].append "hosts", Document.new
|
14
|
+
root["etc"]["hosts"].contents = "127.0.0.1 localhost"
|
15
|
+
|
16
|
+
xml = root.save_to_xml #<=
|
17
|
+
#:invisible_retval:
|
18
|
+
xml.write $stdout,2
|