nom-xml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem 'simplecov', :platform => :ruby_19
6
+ gem 'rcov', :platform => :ruby_18
data/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Copyright © 2012 by The Board of Trustees of the Leland Stanford Junior University. All rights reserved.
2
+
3
+ Redistribution and use of this distribution in source and binary forms, with or without modification, are permitted provided that:
4
+
5
+ The above copyright notice and this permission notice appear in all copies and supporting documentation.
6
+
7
+ The name, identifiers, and trademarks of The Board of Trustees of the Leland Stanford Junior University are not used in advertising or publicity without the express prior written permission of The Board of Trustees of the Leland Stanford Junior University.
8
+
9
+ Recipients acknowledge that this distribution is made available as a research courtesy, “as is”, potentially with defects, without any obligation on the part of The Board of Trustees of the Leland Stanford Junior University to provide support, services, or repair.
10
+
11
+ THE BOARD OF TRUSTEES OF THE LELAND STANFORD JUNIOR UNIVERSITY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE BOARD OF TRUSTEES OF THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # NOM
2
+
3
+ [![Build Status](https://secure.travis-ci.org/cbeer/nom.png)](http://travis-ci.org/cbeer/nom)
4
+
5
+ A library to help you tame sprawling XML schemas
6
+
7
+ NOM allows you to define a “terminology” to ease translation between XML and ruby objects – you can query the xml for Nodes or node values without ever writing a line of XPath.
8
+
9
+
10
+ Some Handy Links
11
+ ----------------
12
+ [API](http://rubydoc.info/github/cbeer/nom) - A reference to NOM's classes
13
+ [#projecthydra](http://webchat.freenode.net/?channels=#projecthydra) on irc.freenode.net
14
+ [Project Hydra Google Group](http://groups.google.com/group/hydra-tech) - community mailing list and forum
15
+
16
+ An Example
17
+ ---------------
18
+
19
+ ```xml
20
+ <?xml version="1.0"?>
21
+ <!-- from http://www.alistapart.com/d/usingxml/xml_uses_a.html -->
22
+ <nutrition>
23
+ <food>
24
+ <name>Avocado Dip</name>
25
+ <mfr>Sunnydale</mfr>
26
+ <serving units="g">29</serving>
27
+ <calories total="110" fat="100"/>
28
+ <total-fat>11</total-fat>
29
+ <saturated-fat>3</saturated-fat>
30
+ <cholesterol>5</cholesterol>
31
+ <sodium>210</sodium>
32
+ <carb>2</carb>
33
+ <fiber>0</fiber>
34
+ <protein>1</protein>
35
+ <vitamins>
36
+ <a>0</a>
37
+ <c>0</c>
38
+ </vitamins>
39
+ <minerals>
40
+ <ca>0</ca>
41
+ <fe>0</fe>
42
+ </minerals>
43
+ </food>
44
+ </nutrition>
45
+ ```
46
+
47
+ ```ruby
48
+ doc = Nokogiri::XML my_source_document
49
+
50
+ doc.set_terminology do |t|
51
+ t.name
52
+
53
+ t.vitamins do |v|
54
+ v.a
55
+ v.c
56
+ end
57
+
58
+ t.minerals do |m|
59
+ m.calcium :path => 'ca'
60
+ m.iron :path => 'fe'
61
+ end
62
+ end
63
+
64
+ doc.nom!
65
+
66
+ doc.name.text == 'Avocado Dip'
67
+ doc.minerals.calcium.text == '0'
68
+ ```
69
+
70
+
71
+
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'bundler/gem_tasks'
4
+
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+
13
+ task :default => :ci
14
+
15
+ require 'rspec/core/rake_task'
16
+ desc "Run specs"
17
+ RSpec::Core::RakeTask.new do |t|
18
+
19
+ if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.8/
20
+ t.rcov = true
21
+ t.rcov_opts = %w{--exclude spec\/*,gems\/*,ruby\/* --aggregate coverage.data}
22
+ end
23
+ end
24
+
25
+ require 'yard'
26
+ YARD::Rake::YardocTask.new do |t|
27
+ t.options = ["--readme", "README.md"]
28
+ end
29
+
30
+ desc "Continuous Integration build"
31
+ task :ci do
32
+ Rake::Task['spec'].invoke
33
+ Rake::Task['yard'].invoke
34
+ end
data/lib/nom.rb ADDED
@@ -0,0 +1 @@
1
+ require 'nom/xml'
data/lib/nom/xml.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'nokogiri'
2
+
3
+ module Nom
4
+ module XML
5
+ require 'nom/xml/version'
6
+ require 'nom/xml/terminology'
7
+ require 'nom/xml/decorators'
8
+
9
+ require 'nom/xml/nokogiri_extension'
10
+
11
+ Nokogiri::XML::Document.send(:include, NokogiriExtension)
12
+ end
13
+ end
14
+
@@ -0,0 +1,6 @@
1
+ module Nom::XML
2
+ module Decorators
3
+ require 'nom/xml/decorators/terminology'
4
+ require 'nom/xml/decorators/nodeset'
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ module Nom::XML::Decorators::NodeSet
2
+ def method_missing sym, *args, &block
3
+ if self.all? { |node| node.respond_to? sym }
4
+ result = self.collect { |node| node.send(sym, *args, &block) }.flatten
5
+ self.class.new(self.document, result) rescue result
6
+ else
7
+ super
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ module Nom::XML::Decorators::Terminology
2
+ def self.extended klass
3
+
4
+ klass.add_terminology_methods!
5
+ end
6
+
7
+ def terms
8
+ @terms ||= []
9
+ end
10
+
11
+ def terms= terms
12
+ @terms = terms
13
+ end
14
+
15
+ def add_terminology_methods!
16
+ document.add_terminology_methods(self)
17
+ end
18
+ end
@@ -0,0 +1,84 @@
1
+ module Nom::XML
2
+ module NokogiriExtension
3
+
4
+ def nom!
5
+ unless decorators(Nokogiri::XML::Node).include? Nom::XML::Decorators::Terminology
6
+ decorators(Nokogiri::XML::Node) << Nom::XML::Decorators::Terminology
7
+ decorate!
8
+ end
9
+
10
+ unless decorators(Nokogiri::XML::NodeSet).include? Nom::XML::Decorators::NodeSet
11
+ decorators(Nokogiri::XML::NodeSet) << Nom::XML::Decorators::NodeSet
12
+ decorate!
13
+ end
14
+
15
+ self
16
+ end
17
+
18
+ def set_terminology &block
19
+ @terminology = Nom::XML::Terminology.new &block
20
+ end
21
+
22
+ def terminology
23
+ @terminology ||= Nom::XML::Terminology.new
24
+ end
25
+
26
+ ##
27
+ # Add terminology accessors for querying child terms
28
+ # @param [Nokogiri::XML::Node] node
29
+ def add_terminology_methods node
30
+ if node == node.document.root or node.is_a? Nokogiri::XML::Document
31
+ node.terms = root_terms(node)
32
+ elsif not node.parent.terms.empty?
33
+ node.terms = child_terms(node)
34
+ end
35
+
36
+ node.terms.each do |k, t|
37
+ (class << node; self; end).send(:define_method, k.to_sym) do
38
+ if self.is_a? Nokogiri::XML::Document
39
+ result = self.root.xpath(t.local_xpath)
40
+ else
41
+ result = self.xpath(t.local_xpath)
42
+ end
43
+ m = t.options[:accessor]
44
+ case
45
+ when m.nil?
46
+ result
47
+ when m.is_a?(Symbol)
48
+ result.collect { |r| r.send(m) }
49
+ when m.is_a?(Proc)
50
+ result.collect { |r| m.call(r) }
51
+ else
52
+ raise "Unknown accessor class: #{m.class}"
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def root_terms node
61
+ node.document.terminology.terms
62
+ end
63
+
64
+ def child_terms node
65
+ h = {}
66
+
67
+ terms_for_node(node).each do |k,v|
68
+ v.terms.each do |k1, v1|
69
+ h[k1] = v1
70
+ end
71
+ end
72
+
73
+ h
74
+ end
75
+
76
+ ##
77
+ #find this node in the terminology
78
+ def terms_for_node node
79
+ node.parent.terms.select do |k,term|
80
+ node.parent.xpath(term.local_xpath).include? node
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,129 @@
1
+ module Nom::XML
2
+ class Term
3
+ attr_reader :name
4
+ attr_reader :terms
5
+ attr_reader :parent
6
+ attr_writer :parent
7
+ attr_reader :options
8
+
9
+ def initialize parent, name, options = {}, *args, &block
10
+ @name = name
11
+ @terms = {}
12
+ @parent = parent
13
+ @options = options || {}
14
+
15
+ in_edit_context do
16
+ yield(self) if block_given?
17
+ end
18
+ end
19
+
20
+ def in_edit_context &block
21
+ @edit_context = true
22
+ yield
23
+ @edit_context = false
24
+ end
25
+
26
+ def terms_from_node node
27
+ terms.select do |k, term|
28
+ node.parent.xpath(term.xpath).include? node
29
+ end.flatten
30
+ end
31
+
32
+ def in_edit_context?
33
+ @edit_context
34
+ end
35
+
36
+ def parent_xpath
37
+ @parent_xpath ||= self.parent.xpath
38
+ end
39
+
40
+ def clear_parent_cache
41
+ @parent_xpath = nil
42
+ end
43
+
44
+ def xpath
45
+ [parent_xpath, local_xpath].flatten.compact.join("/")
46
+ end
47
+
48
+ def local_xpath
49
+ (options[:path] || name).to_s
50
+ end
51
+
52
+ def method_missing method, *args, &block
53
+ if in_edit_context?
54
+ add_term(method, *args, &block)
55
+ elsif key?(method)
56
+ term(method)
57
+ # else if options[:ref]
58
+ # resolve_ref_and_return_term(method, *args, &block)
59
+ else
60
+ super
61
+ end
62
+ #terms[method]
63
+ end
64
+
65
+ def key? term
66
+ terms.key? term
67
+ end
68
+
69
+ def substitute_parent p
70
+ obj = self.dup
71
+
72
+ obj.parent = p
73
+ obj.clear_parent_cache
74
+
75
+ obj
76
+ end
77
+
78
+ protected
79
+ def add_term method, options = {}, *args, &block
80
+ terms[method] = if options[:ref]
81
+ TermRef.new(self, method, options, *args, &block)
82
+ else
83
+ Term.new(self, method, options, *args, &block)
84
+ end
85
+ end
86
+
87
+ def term method, *args, &block
88
+ terms[method]
89
+ end
90
+ end
91
+
92
+ class TermRef < Term
93
+ def ref
94
+ elements = Array(options[:ref])
95
+
96
+ elements.inject(parent) { |memo, mtd| memo.send(mtd) }
97
+ end
98
+
99
+ def key? term
100
+ ref.key? term
101
+ end
102
+
103
+ def local_xpath
104
+ (options[:path] || ref.local_xpath).to_s
105
+ end
106
+
107
+ def method_missing *args, &block
108
+ if in_edit_context?
109
+ super
110
+ else
111
+ ref.method_missing(*args, &block).substitute_parent(self)
112
+ end
113
+ end
114
+ end
115
+
116
+ class Terminology < Term
117
+ def initialize *args, &block
118
+ @terms = {}
119
+ in_edit_context do
120
+ yield(self) if block_given?
121
+ end
122
+ end
123
+
124
+
125
+ def xpath
126
+ nil
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,5 @@
1
+ module Nom
2
+ module XML
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
data/nom.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "nom/xml/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nom-xml"
7
+ s.version = Nom::XML::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Chris Beer"]
10
+ s.email = %q{cabeer@stanford.edu}
11
+ s.homepage = %q{http://github.com/cbeer/nom}
12
+ s.summary = %q{ asdf }
13
+ s.description = %q{ asdfgh }
14
+
15
+ s.add_dependency 'nokogiri'
16
+
17
+ s.add_development_dependency "rspec"
18
+ s.add_development_dependency "rake"
19
+ s.add_development_dependency "yard"
20
+ s.add_development_dependency "redcarpet"
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.extra_rdoc_files = [
26
+ "LICENSE",
27
+ "README.md"
28
+ ]
29
+ s.require_paths = ["lib"]
30
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Nutrition" do
4
+ let(:file) { File.open(File.join(File.dirname(__FILE__), '..', 'fixtures', 'nutrition.xml'), 'r') }
5
+ let(:xml) { Nokogiri::XML(file) }
6
+
7
+ subject {
8
+ xml.set_terminology do |t|
9
+ t.daily_values :path => 'daily-values' do |dv|
10
+ dv.total_fat :path => 'total-fat' do |tf|
11
+ tf.value :path => '.', :accessor => lambda { |node| node.text.to_i }
12
+ tf.units :path => '@units'
13
+ end
14
+ end
15
+
16
+ t.foods :path => 'food' do |food|
17
+ food._name :path => 'name'
18
+ food.mfr
19
+
20
+ food.total_fat :path => 'total-fat' do |tf|
21
+ tf.value :path => '.', :accessor => lambda { |node| node.text.to_i }
22
+ end
23
+ end
24
+ end
25
+
26
+ xml.nom!
27
+
28
+ xml
29
+ }
30
+
31
+ it "should have total fat information" do
32
+ subject.daily_values.total_fat.text.should == "65"
33
+ subject.daily_values.total_fat.value.should include(65)
34
+ subject.daily_values.total_fat.units.text.should =='g'
35
+
36
+ subject.foods.total_fat.value.inject(:+).should == 117
37
+ end
38
+
39
+ it "should have food names" do
40
+ subject.foods._name.text.should include("Avocado Dip")
41
+ end
42
+ end
@@ -0,0 +1,236 @@
1
+ <?xml version="1.0"?>
2
+ <?xml-stylesheet type="text/css" href="nutrition.css"?>
3
+ <nutrition>
4
+ <!-- sample from http://www.alistapart.com/d/usingxml/xml_uses_a.html -->
5
+
6
+ <daily-values>
7
+ <total-fat units="g">65</total-fat>
8
+ <saturated-fat units="g">20</saturated-fat>
9
+ <cholesterol units="mg">300</cholesterol>
10
+ <sodium units="mg">2400</sodium>
11
+ <carb units="g">300</carb>
12
+ <fiber units="g">25</fiber>
13
+ <protein units="g">50</protein>
14
+ </daily-values>
15
+
16
+ <food>
17
+ <name>Avocado Dip</name>
18
+ <mfr>Sunnydale</mfr>
19
+ <serving units="g">29</serving>
20
+ <calories total="110" fat="100"/>
21
+ <total-fat>11</total-fat>
22
+ <saturated-fat>3</saturated-fat>
23
+ <cholesterol>5</cholesterol>
24
+ <sodium>210</sodium>
25
+ <carb>2</carb>
26
+ <fiber>0</fiber>
27
+ <protein>1</protein>
28
+ <vitamins>
29
+ <a>0</a>
30
+ <c>0</c>
31
+ </vitamins>
32
+ <minerals>
33
+ <ca>0</ca>
34
+ <fe>0</fe>
35
+ </minerals>
36
+ </food>
37
+
38
+ <food>
39
+ <name>Bagels, New York Style </name>
40
+ <mfr>Thompson</mfr>
41
+ <serving units="g">104</serving>
42
+ <calories total="300" fat="35"/>
43
+ <total-fat>4</total-fat>
44
+ <saturated-fat>1</saturated-fat>
45
+ <cholesterol>0</cholesterol>
46
+ <sodium>510</sodium>
47
+ <carb>54</carb>
48
+ <fiber>3</fiber>
49
+ <protein>11</protein>
50
+ <vitamins>
51
+ <a>0</a>
52
+ <c>0</c>
53
+ </vitamins>
54
+ <minerals>
55
+ <ca>8</ca>
56
+ <fe>20</fe>
57
+ </minerals>
58
+ </food>
59
+
60
+ <food>
61
+ <name>Beef Frankfurter, Quarter Pound </name>
62
+ <mfr>Armitage</mfr>
63
+ <serving units="g">115</serving>
64
+ <calories total="370" fat="290"/>
65
+ <total-fat>32</total-fat>
66
+ <saturated-fat>15</saturated-fat>
67
+ <cholesterol>65</cholesterol>
68
+ <sodium>1100</sodium>
69
+ <carb>8</carb>
70
+ <fiber>0</fiber>
71
+ <protein>13</protein>
72
+ <vitamins>
73
+ <a>0</a>
74
+ <c>2</c>
75
+ </vitamins>
76
+ <minerals>
77
+ <ca>1</ca>
78
+ <fe>6</fe>
79
+ </minerals>
80
+ </food>
81
+
82
+ <food>
83
+ <name>Chicken Pot Pie</name>
84
+ <mfr>Lakeson</mfr>
85
+ <serving units="g">198</serving>
86
+ <calories total="410" fat="200"/>
87
+ <total-fat>22</total-fat>
88
+ <saturated-fat>9</saturated-fat>
89
+ <cholesterol>25</cholesterol>
90
+ <sodium>810</sodium>
91
+ <carb>42</carb>
92
+ <fiber>2</fiber>
93
+ <protein>10</protein>
94
+ <vitamins>
95
+ <a>20</a>
96
+ <c>2</c>
97
+ </vitamins>
98
+ <minerals>
99
+ <ca>2</ca>
100
+ <fe>10</fe>
101
+ </minerals>
102
+ </food>
103
+
104
+ <food>
105
+ <name>Cole Slaw</name>
106
+ <mfr>Fresh Quick</mfr>
107
+ <serving units=" cup">1.5</serving>
108
+ <calories total="20" fat="0"/>
109
+ <total-fat>0</total-fat>
110
+ <saturated-fat>0</saturated-fat>
111
+ <cholesterol>0</cholesterol>
112
+ <sodium>15</sodium>
113
+ <carb>5</carb>
114
+ <fiber>2</fiber>
115
+ <protein>1</protein>
116
+ <vitamins>
117
+ <a>30</a>
118
+ <c>45</c>
119
+ </vitamins>
120
+ <minerals>
121
+ <ca>4</ca>
122
+ <fe>2</fe>
123
+ </minerals>
124
+ </food>
125
+
126
+ <food>
127
+ <name>Eggs</name>
128
+ <mfr>Goodpath</mfr>
129
+ <serving units="g">50</serving>
130
+ <calories total="70" fat="40"/>
131
+ <total-fat>4.5</total-fat>
132
+ <saturated-fat>1.5</saturated-fat>
133
+ <cholesterol>215</cholesterol>
134
+ <sodium>65</sodium>
135
+ <carb>1</carb>
136
+ <fiber>0</fiber>
137
+ <protein>6</protein>
138
+ <vitamins>
139
+ <a>6</a>
140
+ <c>0</c>
141
+ </vitamins>
142
+ <minerals>
143
+ <ca>2</ca>
144
+ <fe>4</fe>
145
+ </minerals>
146
+ </food>
147
+
148
+ <food>
149
+ <name>Hazelnut Spread</name>
150
+ <mfr>Ferreira</mfr>
151
+ <serving units="tbsp">2</serving>
152
+ <calories total="200" fat="90"/>
153
+ <total-fat>10</total-fat>
154
+ <saturated-fat>2</saturated-fat>
155
+ <cholesterol>0</cholesterol>
156
+ <sodium>20</sodium>
157
+ <carb>23</carb>
158
+ <fiber>2</fiber>
159
+ <protein>3</protein>
160
+ <vitamins>
161
+ <a>0</a>
162
+ <c>0</c>
163
+ </vitamins>
164
+ <minerals>
165
+ <ca>6</ca>
166
+ <fe>4</fe>
167
+ </minerals>
168
+ </food>
169
+
170
+ <food>
171
+ <name>Potato Chips</name>
172
+ <mfr>Lees</mfr>
173
+ <serving units="g">28</serving>
174
+ <calories total="150" fat="90"/>
175
+ <total-fat>10</total-fat>
176
+ <saturated-fat>3</saturated-fat>
177
+ <cholesterol>0</cholesterol>
178
+ <sodium>180</sodium>
179
+ <carb>15</carb>
180
+ <fiber>1</fiber>
181
+ <protein>2</protein>
182
+ <vitamins>
183
+ <a>0</a>
184
+ <c>10</c>
185
+ </vitamins>
186
+ <minerals>
187
+ <ca>0</ca>
188
+ <fe>0</fe>
189
+ </minerals>
190
+ </food>
191
+
192
+ <food>
193
+ <name>Soy Patties, Grilled</name>
194
+ <mfr>Gardenproducts</mfr>
195
+ <serving units="g">96</serving>
196
+ <calories total="160" fat="45"/>
197
+ <total-fat>5</total-fat>
198
+ <saturated-fat>0</saturated-fat>
199
+ <cholesterol>0</cholesterol>
200
+ <sodium>420</sodium>
201
+ <carb>10</carb>
202
+ <fiber>4</fiber>
203
+ <protein>9</protein>
204
+ <vitamins>
205
+ <a>0</a>
206
+ <c>0</c>
207
+ </vitamins>
208
+ <minerals>
209
+ <ca>0</ca>
210
+ <fe>0</fe>
211
+ </minerals>
212
+ </food>
213
+
214
+ <food>
215
+ <name>Truffles, Dark Chocolate</name>
216
+ <mfr>Lyndon's</mfr>
217
+ <serving units="g">39</serving>
218
+ <calories total="220" fat="170"/>
219
+ <total-fat>19</total-fat>
220
+ <saturated-fat>14</saturated-fat>
221
+ <cholesterol>25</cholesterol>
222
+ <sodium>10</sodium>
223
+ <carb>16</carb>
224
+ <fiber>1</fiber>
225
+ <protein>1</protein>
226
+ <vitamins>
227
+ <a>0</a>
228
+ <c>0</c>
229
+ </vitamins>
230
+ <minerals>
231
+ <ca>0</ca>
232
+ <fe>0</fe>
233
+ </minerals>
234
+ </food>
235
+
236
+ </nutrition>
File without changes
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nom::XML::NokogiriExtension do
4
+ let(:doc) {
5
+ Nokogiri::XML(<<-eoxml)
6
+ <item>
7
+ <title>foo</title>
8
+ <description>this is the foo thing</description>
9
+ <nested>
10
+ <second_level>value</second_level>
11
+
12
+ <further_nesting>
13
+ <third_level>3rd</third_level>
14
+ </further_nesting>
15
+ </nested>
16
+ </item>
17
+ eoxml
18
+ }
19
+ describe "#add_terminology_methods" do
20
+ context "root node" do
21
+ it "should add terminology methods to the root node" do
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ require "spec_helper"
2
+
3
+ describe Nom::XML::Decorators::Terminology do
4
+
5
+ end
6
+
File without changes
@@ -0,0 +1,12 @@
1
+ if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.9/
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ end
5
+
6
+ require 'rspec/autorun'
7
+ require 'nom'
8
+
9
+ RSpec.configure do |config|
10
+
11
+ end
12
+
data/spec/test_spec.rb ADDED
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nom::XML do
4
+
5
+ it "should do stuff with terminologies" do
6
+ doc = Nokogiri::XML <<-eos
7
+ <root>
8
+ <element_a>a value</element_a>
9
+ <element_b>
10
+ <element_c>c value</element_c>
11
+ </element_b>
12
+ <element_d>
13
+ <element_e>
14
+ <element_f foo="bar">f value</element_f>
15
+ </element_e>
16
+ </element_d>
17
+ <element_g>
18
+ <element_h>h value 1</element_h>
19
+ <element_h>h value 2</element_h>
20
+ </element_g>
21
+ <element_g>
22
+ <element_h>h value 3</element_h>
23
+ </element_g>
24
+ </root>
25
+ eos
26
+
27
+ doc.set_terminology do |t|
28
+ t.element_a
29
+ t.element_b do |n|
30
+ n.element_c
31
+ end
32
+ t.element_d do |n|
33
+ n.element_e do |e|
34
+ e.element_f
35
+ e.foo :path => 'element_f/@foo'
36
+ e.foo_text :path => 'element_f/@foo', :accessor => :text
37
+ end
38
+ end
39
+ t.element_g do |n|
40
+ n.element_h :accessor => :text
41
+ n.whatever :path => "*", :accessor => lambda { |node| [node.name,node.text].join(':') }
42
+ end
43
+ end
44
+
45
+ doc.nom!
46
+
47
+ doc.root.element_a.text.should == 'a value'
48
+ doc.root.element_b.element_c.text.should == 'c value'
49
+ doc.root.element_d.element_e.element_f.text.strip.should == 'f value'
50
+ doc.root.element_d.element_e.foo.collect(&:text).should == ['bar']
51
+ doc.root.element_d.element_e.foo_text.should == ['bar']
52
+ doc.root.element_g.first.element_h.should == ['h value 1','h value 2']
53
+ doc.root.element_g.element_h.should == ['h value 1','h value 2','h value 3']
54
+ doc.root.element_g.whatever.should == ['element_h:h value 1','element_h:h value 2','element_h:h value 3']
55
+ end
56
+ end
57
+
58
+ describe Nom do
59
+ ### High level goals
60
+ #Given a tree like:
61
+ # <level1>
62
+ # <level2 id="parent1">
63
+ # <level3 id="target1"/>
64
+ # <level3 id="target1"/>
65
+ # </level2>
66
+ # <level2 id="parent2">
67
+ # <level3 id="target3"/>
68
+ # </level2>
69
+ # </level1>
70
+
71
+ it "Should be able to query for all the 'level3' nodes (leafs with different parents)"
72
+ it "Should be able to query for all the 'level3' nodes that are children of parent1 (leafs with same parent)"
73
+ it "Should be able to query for the nth child of a specific node"
74
+ it "Should be able to update the inner text of a specific target node"
75
+ it "Should be able to update the inner texts of a bunch of nodes????? (e.g. find('level2 > level3').innerText=['one', 'two', 'three']"
76
+ it "Should be able to add a subtree at a specific point in the graph"
77
+ it "Should be able to remove a subtree from the graph"
78
+ it "should be able to set the text content of a node to nil"
79
+
80
+ end
metadata ADDED
@@ -0,0 +1,162 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nom-xml
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Beer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: yard
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: redcarpet
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: ! ' asdfgh '
95
+ email: cabeer@stanford.edu
96
+ executables: []
97
+ extensions: []
98
+ extra_rdoc_files:
99
+ - LICENSE
100
+ - README.md
101
+ files:
102
+ - Gemfile
103
+ - LICENSE
104
+ - README.md
105
+ - Rakefile
106
+ - lib/nom.rb
107
+ - lib/nom/xml.rb
108
+ - lib/nom/xml/decorators.rb
109
+ - lib/nom/xml/decorators/nodeset.rb
110
+ - lib/nom/xml/decorators/terminology.rb
111
+ - lib/nom/xml/nokogiri_extension.rb
112
+ - lib/nom/xml/terminology.rb
113
+ - lib/nom/xml/version.rb
114
+ - nom.gemspec
115
+ - spec/examples/nutrition_example_spec.rb
116
+ - spec/fixtures/nutrition.xml
117
+ - spec/lib/nodeset_decorator_spec.rb
118
+ - spec/lib/nokogiri_extension_spec.rb
119
+ - spec/lib/terminology_decorator_spec.rb
120
+ - spec/lib/terminology_spec.rb
121
+ - spec/spec_helper.rb
122
+ - spec/test_spec.rb
123
+ homepage: http://github.com/cbeer/nom
124
+ licenses: []
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ segments:
136
+ - 0
137
+ hash: 1208570413108466077
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ segments:
145
+ - 0
146
+ hash: 1208570413108466077
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 1.8.23
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: asdf
153
+ test_files:
154
+ - spec/examples/nutrition_example_spec.rb
155
+ - spec/fixtures/nutrition.xml
156
+ - spec/lib/nodeset_decorator_spec.rb
157
+ - spec/lib/nokogiri_extension_spec.rb
158
+ - spec/lib/terminology_decorator_spec.rb
159
+ - spec/lib/terminology_spec.rb
160
+ - spec/spec_helper.rb
161
+ - spec/test_spec.rb
162
+ has_rdoc: