traverse 0.0.1
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 +5 -0
- data/Gemfile +4 -0
- data/README.md +3 -0
- data/Rakefile +6 -0
- data/lib/traverse/version.rb +3 -0
- data/lib/traverse.rb +69 -0
- data/spec/spec.rb +91 -0
- data/traverse.gemspec +22 -0
- metadata +67 -0
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
data/lib/traverse.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require "traverse/version"
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
module Traverse
|
6
|
+
class Document
|
7
|
+
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
|
17
|
+
|
18
|
+
if text_node?
|
19
|
+
define_singleton_method "text" do
|
20
|
+
@document.children.first.content
|
21
|
+
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
|
29
|
+
end
|
30
|
+
else
|
31
|
+
define_singleton_method "#{name}s" do
|
32
|
+
children.map { |child| Document.new child }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def [] attr
|
40
|
+
@document.get_attribute attr
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def method_missing m, *args, &block
|
45
|
+
self[m] or super
|
46
|
+
end
|
47
|
+
|
48
|
+
def text_node?
|
49
|
+
num_children = @document.children.count
|
50
|
+
return false unless num_children == 1
|
51
|
+
|
52
|
+
@document.children.first.is_a? Nokogiri::XML::Text
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module Proxy
|
57
|
+
private
|
58
|
+
def proxy *args
|
59
|
+
if args.empty?
|
60
|
+
@proxy
|
61
|
+
else
|
62
|
+
@proxy = args.first
|
63
|
+
def method_missing m
|
64
|
+
@proxy.send m
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/spec/spec.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
$:.push '../'
|
2
|
+
require 'traverse'
|
3
|
+
|
4
|
+
gem 'minitest'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require 'minitest/pride'
|
7
|
+
|
8
|
+
xml = %{
|
9
|
+
<book title="Vineland" author="Thomas Pynchon">
|
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 & Dixon" />
|
17
|
+
<book title="Against the Day" />
|
18
|
+
<book title="Inherent Vice" />
|
19
|
+
</author>
|
20
|
+
<epigraph author="Johnny Copeland">
|
21
|
+
Every dog has his day,
|
22
|
+
and a good dog
|
23
|
+
just might have two days.
|
24
|
+
</epigraph>
|
25
|
+
<quotations>
|
26
|
+
<quotation>
|
27
|
+
Up and down that street, she remembered, television screens had
|
28
|
+
flickered silent blue in the darkness. Strange loud birds, not of the
|
29
|
+
neighborhood, were attracted, some content to perch in the palm
|
30
|
+
trees, keeping silence and an eye out for the rats who lived in the
|
31
|
+
fronds, others flying by close to windows, seeking an angle to sit
|
32
|
+
and view the picture from. When the commercials came on, the birds,
|
33
|
+
with voices otherworldly pure, would sing back at them, sometimes
|
34
|
+
even when none were on.
|
35
|
+
</quotation>
|
36
|
+
<quotation>
|
37
|
+
Takeshi recognized his acquaintance Minoru, a government bomb-squad
|
38
|
+
expert. Not a genius, exactly, more like an idiot savant with X-ray
|
39
|
+
vision.
|
40
|
+
</quotation>
|
41
|
+
</quotes>
|
42
|
+
<review reviewer="Salman Rushdie">
|
43
|
+
What is interesting is to have before us, at the end of the Greed
|
44
|
+
Decade, that rarest of birds: a major political novel about what
|
45
|
+
America has been doing to itself, to its children, all these many
|
46
|
+
years.
|
47
|
+
</review>
|
48
|
+
<text text="seriously, who writes XML like this">
|
49
|
+
I mean, rilly.
|
50
|
+
</text>
|
51
|
+
</book>
|
52
|
+
}
|
53
|
+
|
54
|
+
describe Traverse::Document do
|
55
|
+
before do
|
56
|
+
@doc = Traverse::Document.new xml
|
57
|
+
end
|
58
|
+
|
59
|
+
it "helps you access attributes" do
|
60
|
+
@doc.book.title.must_equal "Vineland"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "also helps you access attributes shadowed by children" do
|
64
|
+
@doc.book.author.wont_equal "Thomas Pynchon"
|
65
|
+
@doc.book['author'].must_equal "Thomas Pynchon"
|
66
|
+
@doc.book.author.name.must_equal "Thomas Pynchon"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "helps you get at child nodes" do
|
70
|
+
@doc.book.review.reviewer.must_equal "Salman Rushdie"
|
71
|
+
@doc.book.epigraph.author.must_equal "Johnny Copeland"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "knows when a node contains only text" do
|
75
|
+
assert @doc.book.epigraph.send(:text_node?)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "handles annoying text nodes transparently" do
|
79
|
+
@doc.book.epigraph.text.must_match(/Every dog has his day/)
|
80
|
+
@doc.book.review.text.must_match(/that rarest of birds/)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "nevertheless handles attributes named 'text'" do
|
84
|
+
@doc.book.text['text'].must_match(/seriously/)
|
85
|
+
@doc.book.text.text.must_match(/rilly/)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "knows to collect children with the same name" do
|
89
|
+
@doc.book.author.books.count.must_equal 8
|
90
|
+
end
|
91
|
+
end
|
data/traverse.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "traverse/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "traverse"
|
7
|
+
s.version = Traverse::VERSION
|
8
|
+
s.authors = ["happy4crazy"]
|
9
|
+
s.email = ["alan.m.odonnell@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/happy4crazy/traverse"
|
11
|
+
s.summary = %q{Easily traverse an XML document.}
|
12
|
+
s.description = %q{Easily traverse an XML document.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "traverse"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency 'nokogiri', '~> 1.5'
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: traverse
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- happy4crazy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-02 00:00:00.000000000 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: nokogiri
|
17
|
+
requirement: &2164471840 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1.5'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2164471840
|
26
|
+
description: Easily traverse an XML document.
|
27
|
+
email:
|
28
|
+
- alan.m.odonnell@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- Gemfile
|
35
|
+
- README.md
|
36
|
+
- Rakefile
|
37
|
+
- lib/traverse.rb
|
38
|
+
- lib/traverse/version.rb
|
39
|
+
- spec/spec.rb
|
40
|
+
- traverse.gemspec
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: https://github.com/happy4crazy/traverse
|
43
|
+
licenses: []
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project: traverse
|
62
|
+
rubygems_version: 1.6.2
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Easily traverse an XML document.
|
66
|
+
test_files:
|
67
|
+
- spec/spec.rb
|