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 CHANGED
@@ -3,3 +3,5 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .rvmrc
6
+ *.swp
7
+ .DS_Store
@@ -1,3 +1,3 @@
1
1
  module Traverse
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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
- if document.is_a? String
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
- else
23
- @document.children.reject do |child|
24
- child.is_a? Nokogiri::XML::Text
25
- end.group_by(&:name).each do |name, children|
26
- if children.count == 1
27
- define_singleton_method "#{name}" do
28
- Document.new children.first
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 "#{name}s" do
32
- children.map { |child| Document.new child }
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 title="V" />
12
- <book title="The Crying of Lot 49" />
13
- <book title="Gravity's Rainbow" />
14
- <book title="Slow Learner" />
15
- <book title="Vineland" />
16
- <book title="Mason &amp; Dixon" />
17
- <book title="Against the Day" />
18
- <book title="Inherent Vice" />
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 &amp; 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.1
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-02 00:00:00.000000000 -04:00
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: &2164471840 !ruby/object:Gem::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: *2164471840
25
+ version_requirements: *2157314300
26
26
  description: Easily traverse an XML document.
27
27
  email:
28
28
  - alan.m.odonnell@gmail.com