traverse 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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