traverse 0.0.1 → 0.0.2
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/.gitignore +2 -0
- data/lib/traverse/version.rb +1 -1
- data/lib/traverse.rb +93 -18
- data/spec/spec.rb +23 -8
- metadata +4 -4
data/.gitignore
CHANGED
data/lib/traverse/version.rb
CHANGED
data/lib/traverse.rb
CHANGED
@@ -1,39 +1,52 @@
|
|
1
1
|
require "traverse/version"
|
2
2
|
require 'nokogiri'
|
3
3
|
require 'open-uri'
|
4
|
+
require 'active_support/inflector'
|
4
5
|
|
5
6
|
module Traverse
|
6
7
|
class Document
|
7
8
|
def initialize document
|
8
|
-
|
9
|
-
begin
|
10
|
-
@document = Nokogiri::XML(document)
|
11
|
-
rescue
|
12
|
-
return nil
|
13
|
-
end
|
14
|
-
else
|
15
|
-
@document = document
|
16
|
-
end
|
9
|
+
setup_underlying_document document
|
17
10
|
|
18
11
|
if text_node?
|
19
12
|
define_singleton_method "text" do
|
20
13
|
@document.children.first.content
|
21
14
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
15
|
+
end
|
16
|
+
|
17
|
+
singular_children.group_by(&:name).each do |name, children|
|
18
|
+
if children.count == 1
|
19
|
+
child = children.first
|
20
|
+
if text_only_node? child
|
21
|
+
define_singleton_method name do
|
22
|
+
child.content.strip
|
29
23
|
end
|
30
24
|
else
|
31
|
-
define_singleton_method
|
32
|
-
|
25
|
+
define_singleton_method name do
|
26
|
+
Document.new child
|
27
|
+
end
|
28
|
+
end
|
29
|
+
else
|
30
|
+
define_singleton_method name.pluralize do
|
31
|
+
children.map do |child|
|
32
|
+
if text_only_node? child
|
33
|
+
child.content.strip
|
34
|
+
else
|
35
|
+
Document.new child
|
36
|
+
end
|
33
37
|
end
|
34
38
|
end
|
35
39
|
end
|
36
40
|
end
|
41
|
+
|
42
|
+
plural_children.each do |pluralized_child|
|
43
|
+
define_singleton_method pluralized_child.name do
|
44
|
+
pluralized_child.children.reject do |baby|
|
45
|
+
baby.class == Nokogiri::XML::Text
|
46
|
+
end.map { |child| Document.new child }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
37
50
|
end
|
38
51
|
|
39
52
|
def [] attr
|
@@ -45,12 +58,74 @@ module Traverse
|
|
45
58
|
self[m] or super
|
46
59
|
end
|
47
60
|
|
61
|
+
def attributes
|
62
|
+
if @document.is_a? Nokogiri::XML::Document
|
63
|
+
[]
|
64
|
+
else
|
65
|
+
@document.attributes
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
48
69
|
def text_node?
|
49
70
|
num_children = @document.children.count
|
50
71
|
return false unless num_children == 1
|
51
72
|
|
52
73
|
@document.children.first.is_a? Nokogiri::XML::Text
|
53
74
|
end
|
75
|
+
|
76
|
+
def text_only_node? node
|
77
|
+
node.children.all? do |child|
|
78
|
+
child.is_a? Nokogiri::XML::Text
|
79
|
+
end and node.attributes.empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
def real_children
|
83
|
+
@document.children.reject do |child|
|
84
|
+
child.is_a? Nokogiri::XML::Text
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def singular_children
|
89
|
+
real_children.select do |child|
|
90
|
+
child.children.any? do |baby|
|
91
|
+
if baby.class == Nokogiri::XML::Text
|
92
|
+
false # ignore text children
|
93
|
+
else
|
94
|
+
baby.name != child.name.singularize
|
95
|
+
end
|
96
|
+
end or child.children.all? do |baby|
|
97
|
+
baby.class == Nokogiri::XML::Text
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def plural_children
|
103
|
+
real_children.select do |child|
|
104
|
+
child.children.all? do |baby|
|
105
|
+
if baby.class == Nokogiri::XML::Text
|
106
|
+
true
|
107
|
+
else
|
108
|
+
baby.name == child.name.singularize
|
109
|
+
end
|
110
|
+
end and child.children.count > 1
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def setup_underlying_document document
|
115
|
+
if document.is_a? String
|
116
|
+
begin
|
117
|
+
@document = Nokogiri::XML(document)
|
118
|
+
rescue
|
119
|
+
return nil
|
120
|
+
end
|
121
|
+
else
|
122
|
+
@document = document
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def to_s
|
127
|
+
"<Traversable... >"
|
128
|
+
end
|
54
129
|
end
|
55
130
|
|
56
131
|
module Proxy
|
data/spec/spec.rb
CHANGED
@@ -8,14 +8,14 @@ require 'minitest/pride'
|
|
8
8
|
xml = %{
|
9
9
|
<book title="Vineland" author="Thomas Pynchon">
|
10
10
|
<author name="Thomas Pynchon">
|
11
|
-
<book
|
12
|
-
<book
|
13
|
-
<book
|
14
|
-
<book
|
15
|
-
<book
|
16
|
-
<book
|
17
|
-
<book
|
18
|
-
<book
|
11
|
+
<book> V </book>
|
12
|
+
<book> The Crying of Lot 49 </book>
|
13
|
+
<book> Gravity's Rainbow" </book>
|
14
|
+
<book> Slow Learner" </book>
|
15
|
+
<book> Vineland </book>
|
16
|
+
<book> Mason & Dixon </book>
|
17
|
+
<book> Against the Day </book>
|
18
|
+
<book> Inherent Vice </book>
|
19
19
|
</author>
|
20
20
|
<epigraph author="Johnny Copeland">
|
21
21
|
Every dog has his day,
|
@@ -45,6 +45,9 @@ xml = %{
|
|
45
45
|
America has been doing to itself, to its children, all these many
|
46
46
|
years.
|
47
47
|
</review>
|
48
|
+
<pagecount>
|
49
|
+
385
|
50
|
+
</pagecount>
|
48
51
|
<text text="seriously, who writes XML like this">
|
49
52
|
I mean, rilly.
|
50
53
|
</text>
|
@@ -85,7 +88,19 @@ describe Traverse::Document do
|
|
85
88
|
@doc.book.text.text.must_match(/rilly/)
|
86
89
|
end
|
87
90
|
|
91
|
+
it "knows when a node has only text and no attributes" do
|
92
|
+
@doc.book.pagecount.must_equal "385"
|
93
|
+
end
|
94
|
+
|
88
95
|
it "knows to collect children with the same name" do
|
89
96
|
@doc.book.author.books.count.must_equal 8
|
97
|
+
assert @doc.book.author.books.all? do |book|
|
98
|
+
book.is_a? String
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "knows to collect children of a pluralized parent" do
|
103
|
+
@doc.book.quotations.count.must_equal 2
|
104
|
+
@doc.book.quotations.last.text.must_match(/more like an idiot savant/)
|
90
105
|
end
|
91
106
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: traverse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-08-
|
12
|
+
date: 2011-08-03 00:00:00.000000000 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|
17
|
-
requirement: &
|
17
|
+
requirement: &2157314300 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,7 +22,7 @@ dependencies:
|
|
22
22
|
version: '1.5'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2157314300
|
26
26
|
description: Easily traverse an XML document.
|
27
27
|
email:
|
28
28
|
- alan.m.odonnell@gmail.com
|