roxml 3.1.1 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
+ == 3.1.2 (October 18, 2009)
2
+
3
+ * minor enhancements
4
+
5
+ * Retain whitespace in element contents, but still default on blank (rather than entirely empty) elements
6
+
7
+ * bug fixes
8
+
9
+ * Include namespaces in xml output
10
+ * Fix that auto-wrapped collections weren't output with their wrappers
11
+ (which requires introducing the roxml_references accessor on the instance)
12
+
1
13
  == 3.1.1 (October 17, 2009)
2
14
 
3
15
  * bug fix
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -159,3 +159,18 @@ explicitly require one or the other, you may do the following:
159
159
  require 'roxml'
160
160
 
161
161
  For more information on available annotations, see ROXML::ClassMethods::Declarations
162
+
163
+ == Note on Patches/Pull Requests
164
+
165
+ * Fork the project.
166
+ * Make your feature addition or bug fix.
167
+ * Add specs for it. This is important so I don't break it in a
168
+ future version unintentionally.
169
+ * Commit, do not mess with rakefile, version, or history.
170
+ (if you want to have your own version, that is fine but
171
+ bump version in a commit by itself I can ignore when I pull)
172
+ * Send me a pull request. Bonus points for topic branches.
173
+
174
+ == Copyright
175
+
176
+ Copyright (c) 2004-2009 Ben Woosley, Zak Mandhro and Anders Engstrom. See LICENSE for details.
data/TODO CHANGED
@@ -1,8 +1,6 @@
1
1
  Planned:
2
2
 
3
- v 3.1
4
-
5
- * Add xml_namespaces to allow declaration of distinct prefx/url namespace pairs
3
+ v 3.2
6
4
 
7
5
  * Consider class_inheritable_attribute rather than superclass.try stuff.
8
6
 
@@ -35,5 +33,3 @@ v 3.x
35
33
  a singular specification has multiple possible node references
36
34
 
37
35
  * Use lazy evaluation to minimize parsing time for large files
38
-
39
-
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.1
1
+ 3.1.2
data/lib/roxml.rb CHANGED
@@ -13,15 +13,20 @@ module ROXML # :nodoc:
13
13
  ClassMethods::Declarations,
14
14
  ClassMethods::Operations
15
15
  include InstanceMethods
16
+
17
+ attr_accessor :roxml_references
16
18
  end
17
19
  end
18
20
 
19
21
  module InstanceMethods # :nodoc:
20
22
  # Returns an XML object representing this object
21
- def to_xml(name = self.class.tag_name)
22
- XML::Node.create(name.to_s).tap do |root|
23
- self.class.roxml_attrs.each do |attr|
24
- ref = attr.to_ref(self)
23
+ def to_xml(params = {})
24
+ params.reverse_merge!(:name => self.class.tag_name, :namespace => self.class.roxml_namespace)
25
+ XML::Node.create([params[:namespace], params[:name]].compact.join(':')).tap do |root|
26
+ refs = (self.roxml_references.present? \
27
+ ? self.roxml_references \
28
+ : self.class.roxml_attrs.map {|attr| attr.to_ref(self) })
29
+ refs.each do |ref|
25
30
  value = ref.to_xml(self)
26
31
  unless value.nil?
27
32
  ref.update_xml(root, value)
@@ -530,11 +535,13 @@ module ROXML # :nodoc:
530
535
  xml = XML::Node.from(data)
531
536
 
532
537
  new(*initialization_args).tap do |inst|
533
- roxml_attrs.each do |attr|
534
- value = attr.to_ref(inst).value_in(xml)
535
- inst.respond_to?(attr.setter) \
536
- ? inst.send(attr.setter, value) \
537
- : inst.instance_variable_set(attr.instance_variable_name, value)
538
+ inst.roxml_references = roxml_attrs.map {|attr| attr.to_ref(inst) }
539
+
540
+ inst.roxml_references.each do |ref|
541
+ value = ref.value_in(xml)
542
+ inst.respond_to?(ref.opts.setter) \
543
+ ? inst.send(ref.opts.setter, value) \
544
+ : inst.instance_variable_set(ref.opts.instance_variable_name, value)
538
545
  end
539
546
  inst.send(:after_parse) if inst.respond_to?(:after_parse, true)
540
547
  end
@@ -6,6 +6,7 @@ module ROXML
6
6
  # Internal base class that represents an XML - Class binding.
7
7
  #
8
8
  class XMLRef # :nodoc:
9
+ attr_reader :opts
9
10
  delegate :required?, :array?, :blocks, :accessor, :default, :wrapper, :to => :opts
10
11
 
11
12
  def initialize(opts, instance)
@@ -41,8 +42,6 @@ module ROXML
41
42
  end
42
43
 
43
44
  private
44
- attr_reader :opts
45
-
46
45
  def conventionize(what)
47
46
  convention ||= @instance.class.respond_to?(:roxml_naming_convention) && @instance.class.roxml_naming_convention
48
47
  if !what.blank? && convention.respond_to?(:call)
@@ -84,8 +83,12 @@ module ROXML
84
83
  opts.wrapper ? "#{namespacify(opts.wrapper)}/#{xpath_name}" : xpath_name.to_s
85
84
  end
86
85
 
86
+ def auto_wrapper
87
+ namespacify(conventionize(opts.name.pluralize))
88
+ end
89
+
87
90
  def auto_xpath
88
- "#{namespacify(conventionize(opts.name.pluralize))}/#{xpath_name}" if array?
91
+ "#{auto_wrapper}/#{xpath_name}" if array?
89
92
  end
90
93
 
91
94
  def several?
@@ -93,11 +96,13 @@ module ROXML
93
96
  end
94
97
 
95
98
  def wrap(xml)
96
- return xml if !wrapper || xml.name == wrapper
97
- if child = xml.children.find {|c| c.name == wrapper }
99
+ wrap_with = @auto_vals ? auto_wrapper : wrapper
100
+
101
+ return xml if !wrap_with || xml.name == wrap_with
102
+ if child = xml.children.find {|c| c.name == wrap_with }
98
103
  return child
99
104
  end
100
- xml.add_child(XML::Node.create(wrapper.to_s))
105
+ xml.add_child(XML::Node.create(wrap_with.to_s))
101
106
  end
102
107
 
103
108
  def nodes_in(xml)
@@ -166,10 +171,10 @@ module ROXML
166
171
  xml.name = value
167
172
  elsif array?
168
173
  value.each do |v|
169
- add(xml.add_child(XML::Node.create(name)), v)
174
+ add(xml.add_child(XML::Node.create(xpath_name)), v)
170
175
  end
171
176
  else
172
- add(xml.add_child(XML::Node.create(name)), value)
177
+ add(xml.add_child(XML::Node.create(xpath_name)), value)
173
178
  end
174
179
  end
175
180
 
@@ -177,12 +182,12 @@ module ROXML
177
182
  if content? || name?
178
183
  value =
179
184
  if content?
180
- xml.content.to_s.strip
185
+ xml.content.to_s
181
186
  elsif name?
182
187
  xml.name
183
188
  end
184
189
 
185
- if value.empty?
190
+ if value.blank?
186
191
  raise RequiredElementMissing, "#{name} from #{xml} for #{accessor}" if required?
187
192
  default
188
193
  else
@@ -190,7 +195,7 @@ module ROXML
190
195
  end
191
196
  else
192
197
  nodes_in(xml) do |node|
193
- node.content.strip
198
+ node.content
194
199
  end
195
200
  end
196
201
  end
@@ -271,14 +276,15 @@ module ROXML
271
276
  # Updates the composed XML object in the given XML block to
272
277
  # the value provided.
273
278
  def write_xml(xml, value)
279
+ params = {:name => name, :namespace => opts.namespace}
274
280
  if array?
275
281
  value.each do |v|
276
- xml.add_child(v.to_xml(name))
282
+ xml.add_child(v.to_xml(params))
277
283
  end
278
284
  elsif value.is_a?(ROXML)
279
- xml.add_child(value.to_xml(name))
285
+ xml.add_child(value.to_xml(params))
280
286
  else
281
- node = XML::Node.create(name)
287
+ node = XML::Node.create(xpath_name)
282
288
  node.content = value.to_xml
283
289
  xml.add_child(node)
284
290
  end
data/roxml.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{roxml}
8
- s.version = "3.1.1"
8
+ s.version = "3.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ben Woosley", "Zak Mandhro", "Anders Engstrom", "Russ Olsen"]
12
- s.date = %q{2009-10-17}
12
+ s.date = %q{2009-10-18}
13
13
  s.description = %q{ROXML is a Ruby library designed to make it easier for Ruby developers to work with XML.
14
14
  Using simple annotations, it enables Ruby classes to be mapped to XML. ROXML takes care
15
15
  of the marshalling and unmarshalling of mapped attributes so that developers can focus on
@@ -25,7 +25,7 @@ RESTful applications, Web Services, and XML-RPC.
25
25
  ".gitignore",
26
26
  ".gitmodules",
27
27
  "History.txt",
28
- "MIT-LICENSE",
28
+ "LICENSE",
29
29
  "README.rdoc",
30
30
  "Rakefile",
31
31
  "TODO",
@@ -51,7 +51,15 @@ describe ROXML::Definition do
51
51
  <question>&quot;Wickard &amp; Filburn&quot; &gt;</question>
52
52
  <question> &lt; McCulloch &amp; Maryland?</question>
53
53
  </xml>
54
- }).should == ["\"Wickard & Filburn\" >", "< McCulloch & Maryland?"]
54
+ }).should == ["\"Wickard & Filburn\" >", " < McCulloch & Maryland?"]
55
+ end
56
+
57
+ it "should unescape utf characters in xml" do
58
+ ROXML::Definition.new(:questions, :as => []).to_ref(RoxmlObject.new).value_in(%{
59
+ <xml>
60
+ <question>ROXML\342\204\242</question>
61
+ </xml>
62
+ }).should == ["ROXML™"]
55
63
  end
56
64
 
57
65
  describe "attr name" do
@@ -1,32 +1,61 @@
1
1
  require 'spec/spec_helper.rb'
2
2
 
3
3
  describe ROXML, "with namespaces" do
4
- context "when an included namespace is not defined in the xml" do
5
- context "where the missing namespace is the default" do
6
- it "should raise"
4
+ describe "for writing" do
5
+ before do
6
+ @xml = <<EOS
7
+ <?xml version="1.0" encoding="UTF-8"?>
8
+ <gronk:VApp name="My new vApp" status="1" href="https://vcloud.example.com/vapp/833" type="application/vnd.vmware.vcloud.vapp+xml" xmlns:vmw="http://foo.example.com" xmlns:gronk="http://gronk.example.com">
9
+ <gronk:NetworkConfig name="Network 1">
10
+ <vmw:FenceMode>allowInOut</vmw:FenceMode>
11
+ <vmw:Dhcp>true</vmw:Dhcp>
12
+ <gronk:errors>
13
+ <gronk:error>OhNo!</gronk:error>
14
+ <gronk:error>Another!</gronk:error>
15
+ </gronk:errors>
16
+ </gronk:NetworkConfig>
17
+ <foo />
18
+ <bar>
19
+ gronk
20
+ </bar>
21
+ </gronk:VApp>
22
+ EOS
23
+ end
7
24
 
8
- context "but the namespace is declared in the body" do
9
- it "should succeed"
10
- end
25
+ class NetworkConfig
26
+ include ROXML
27
+ xml_namespace :gronk
28
+
29
+ xml_name 'NetworkConfig'
30
+ xml_reader :name, :from => '@name'
31
+ xml_reader :errors, :as => []
32
+ xml_accessor :fence_mode, :from => 'vmw:FenceMode'
33
+ xml_accessor :dhcp?, :from => 'vmw:Dhcp'
11
34
  end
12
-
13
- context "where the missing namespace is included in a namespacey from" do
14
- it "should raise"
15
35
 
16
- context "but the namespace is declared in the body" do
17
- it "should succeed"
18
- end
36
+ class VApp
37
+ include ROXML
38
+ xml_namespace :gronk
39
+
40
+ xml_name "VApp"
41
+ xml_reader :name, :from => '@name'
42
+ xml_reader :status, :from => '@status'
43
+ xml_reader :href, :from => '@href'
44
+ xml_reader :type, :from => '@type'
45
+ xml_accessor :foo, :from => 'foo', :namespace => false
46
+ xml_accessor :bar, :from => 'bar', :namespace => false
47
+ xml_accessor :network_configs, :as => [NetworkConfig], :namespace => :gronk
19
48
  end
20
-
21
- context "where the missing namespace is included in an explicit :namespace" do
22
- it "should raise"
23
49
 
24
- context "but the namespace is declared in the body" do
25
- it "should succeed"
50
+ describe "#to_xml" do
51
+ it "should reproduce the input xml" do
52
+ output = ROXML::XML::Document.new
53
+ output.root = VApp.from_xml(@xml).to_xml
54
+ output.should == ROXML::XML::Parser.parse(@xml)
26
55
  end
27
56
  end
28
57
  end
29
-
58
+
30
59
  describe "roxml namespacey declaration", :shared => true do
31
60
  context "with a namespacey :from" do
32
61
  context "and an explicit :namespace" do
@@ -1,32 +1,60 @@
1
1
  require 'spec/spec_helper.rb'
2
2
 
3
3
  describe ROXML, "#xml_namespaces" do
4
- class Tires
5
- include ROXML
6
-
7
- xml_namespaces \
8
- :bobsbike => 'http://bobsbikes.example.com',
9
- :alicesauto => 'http://alicesautosupply.example.com/'
10
-
11
- xml_reader :bike_tires, :as => [], :from => '@name', :in => 'bobsbike:tire'
12
- xml_reader :car_tires, :as => [], :from => '@name', :in => 'alicesauto:tire'
13
- end
14
-
15
- before do
16
- @xml = %{<?xml version="1.0"?>
17
- <inventory xmlns="http://alicesautosupply.example.com/" xmlns:bike="http://bobsbikes.example.com">
18
- <tire name="super slick racing tire" />
19
- <tire name="all weather tire" />
20
- <bike:tire name="skinny street" />
21
- </inventory>
22
- }
23
- end
4
+ describe "for reading" do
5
+ class Tires
6
+ include ROXML
7
+
8
+ xml_namespaces \
9
+ :bobsbike => 'http://bobsbikes.example.com',
10
+ :alicesauto => 'http://alicesautosupply.example.com/'
11
+
12
+ xml_reader :bike_tires, :as => [], :from => '@name', :in => 'bobsbike:tire'
13
+ xml_reader :car_tires, :as => [], :from => '@name', :in => 'alicesauto:tire'
14
+ end
15
+
16
+ before do
17
+ @xml = %{<?xml version="1.0"?>
18
+ <inventory xmlns="http://alicesautosupply.example.com/" xmlns:bike="http://bobsbikes.example.com">
19
+ <tire name="super slick racing tire" />
20
+ <tire name="all weather tire" />
21
+ <bike:tire name="skinny street" />
22
+ </inventory>
23
+ }
24
+ end
24
25
 
25
- it "should remap default namespaces" do
26
- Tires.from_xml(@xml).car_tires.should =~ ['super slick racing tire', 'all weather tire']
26
+ it "should remap default namespaces" do
27
+ Tires.from_xml(@xml).car_tires.should =~ ['super slick racing tire', 'all weather tire']
28
+ end
29
+
30
+ it "should remap prefix namespaces" do
31
+ Tires.from_xml(@xml).bike_tires.should == ['skinny street']
32
+ end
27
33
  end
28
34
 
29
- it "should remap prefix namespaces" do
30
- Tires.from_xml(@xml).bike_tires.should == ['skinny street']
35
+ context "when an included namespace is not defined in the xml" do
36
+ context "where the missing namespace is the default" do
37
+ it "should raise"
38
+
39
+ context "but the namespace is declared in the body" do
40
+ it "should succeed"
41
+ end
42
+ end
43
+
44
+ context "where the missing namespace is included in a namespacey from" do
45
+ it "should raise"
46
+
47
+ context "but the namespace is declared in the body" do
48
+ it "should succeed"
49
+ end
50
+ end
51
+
52
+ context "where the missing namespace is included in an explicit :namespace" do
53
+ it "should raise"
54
+
55
+ context "but the namespace is declared in the body" do
56
+ it "should succeed"
57
+ end
58
+ end
31
59
  end
32
60
  end
data/tasks/rdoc.rake CHANGED
@@ -7,7 +7,7 @@ Rake::RDocTask.new do |rdoc|
7
7
  end
8
8
 
9
9
  rdoc.rdoc_dir = 'rdoc'
10
- rdoc.title = "roxml-new #{version}"
10
+ rdoc.title = "roxml #{version}"
11
11
  rdoc.rdoc_files.include('README*')
12
12
  rdoc.rdoc_files.include('lib/**/*.rb')
13
13
  end
data/tasks/test.rake CHANGED
@@ -1,30 +1,23 @@
1
1
  require 'rake/testtask'
2
- Rake::TestTask.new(:bugs) do |test|
3
- test.libs << 'lib' << 'test'
4
- test.pattern = 'test/bugs/*_bugs.rb'
5
- test.verbose = true
6
- end
7
-
8
2
  desc "Test ROXML using the default parser selection behavior"
9
3
  task :test do
10
4
  require 'rake/runtest'
5
+ $LOAD_PATH << 'lib'
11
6
  Rake.run_tests 'test/unit/*_test.rb'
12
7
  end
13
8
 
14
9
  namespace :test do
15
10
  desc "Test ROXML under the Nokogiri parser"
16
11
  task :nokogiri do
17
- module ROXML
18
- XML_PARSER = 'nokogiri'
19
- end
12
+ $LOAD_PATH << 'spec'
13
+ require 'spec/support/nokogiri'
20
14
  Rake::Task["test"].invoke
21
15
  end
22
16
 
23
17
  desc "Test ROXML under the LibXML parser"
24
18
  task :libxml do
25
- module ROXML
26
- XML_PARSER = 'libxml'
27
- end
19
+ $LOAD_PATH << 'spec'
20
+ require 'spec/support/libxml'
28
21
  Rake::Task["test"].invoke
29
22
  end
30
23
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Woosley
@@ -12,7 +12,7 @@ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
14
 
15
- date: 2009-10-17 00:00:00 -04:00
15
+ date: 2009-10-18 00:00:00 -04:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -84,7 +84,7 @@ files:
84
84
  - .gitignore
85
85
  - .gitmodules
86
86
  - History.txt
87
- - MIT-LICENSE
87
+ - LICENSE
88
88
  - README.rdoc
89
89
  - Rakefile
90
90
  - TODO
data/MIT-LICENSE DELETED
@@ -1,18 +0,0 @@
1
- The MIT License
2
-
3
- Copyright (c) 2004-2009 by Ben Woosley, Zak Mandhro and Anders Engstrom
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6
- and associated documentation files (the "Software"), to deal in the Software without restriction,
7
- including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
- and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9
- subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all copies or substantial
12
- portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15
- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
16
- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
- USE OR OTHER DEALINGS IN THE SOFTWARE.