rpath 1.0.1 → 1.1.0
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.
- checksums.yaml +5 -13
- data/.yardopts +4 -0
- data/README.md +38 -19
- data/lib/rpath/adapters.rb +1 -0
- data/lib/rpath/adapters/oga.rb +79 -0
- data/lib/rpath/expressions.rb +2 -2
- data/lib/rpath/version.rb +1 -1
- metadata +29 -13
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NDgxYmM5N2EzNjk0N2I3ZDFhM2M2MmU0ZTlmN2M2MjQ2NTA3MjBkOQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ca43180768c5384613ebf5bee029b8e05b7d0875
|
4
|
+
data.tar.gz: 7e86e33589477ab8d9a62e1ccf5dde9154fcf3fc
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
YzgyOWI0ZTFmYWFlNzlkNDNlNGE4ODRkMGI4MjRlN2RiNmEyYThlNTk0YzM3
|
11
|
-
MzVjNDYwM2RiZDNjYThiNmIwMjUwNTRjMmQ3ZGJjODI0ZGY4YmM=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MDIxOTQwM2RhMDYwODY1OWUzY2QyY2NjYzBjNjU1Y2M1Yzg3NzFiNzAyMzQw
|
14
|
-
NTFjMzNiZTg4Y2E5NDFmODQyZGVmY2Y5MTllNWY3YTdlYzgxODgzMTE3ZDEx
|
15
|
-
YjBjNDk3YzYwMmVhY2IwZWZhZTdlNDViODgwZTRkOWQ2ZDM4OTA=
|
6
|
+
metadata.gz: d703e513a8e18b418148812010799d76b140ddebf74f67505772d5ab8a4bfdce69ed65f90c83191d74a0a7831efca6781a40002439e6e8010e0aa3b91bcddc35
|
7
|
+
data.tar.gz: a3ebe23c2b83ca6f24a53ee78e7e04315e7ea5295a730723c678190e5a16b0e10f639ff254b88f9ef536e25caf296d382f573f3092e5b36dbdaaeb601ccdec36
|
data/.yardopts
ADDED
data/README.md
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# RPath
|
2
2
|
|
3
|
-
"Don't
|
3
|
+
"Don't use this." —[flavorjones](https://github.com/flavorjones) [[1]](http://www.nokogiri.org/tutorials/searching_a_xml_html_document.html)
|
4
4
|
|
5
5
|
[](http://badge.fury.io/rb/rpath)
|
6
|
+
[](https://travis-ci.org/jonahb/rpath)
|
6
7
|
|
7
8
|
## Overview
|
8
9
|
|
9
|
-
RPath lets you
|
10
|
+
RPath lets you query graphs, such as XML documents, with just Ruby.
|
10
11
|
|
11
|
-
RPath can operate on [Nokogiri](http://www.nokogiri.org) documents, [REXML](http://www.germane-software.com/software/rexml/) documents, and the filesystem. Building adapters for other graphs is simple.
|
12
|
+
RPath can operate on [Nokogiri](http://www.nokogiri.org) documents, [REXML](http://www.germane-software.com/software/rexml/) documents, [Oga](https://github.com/YorickPeterse/oga) documents, and the filesystem. Building adapters for other graphs is simple.
|
12
13
|
|
13
14
|
Leading members of the Ruby community have [warned against](http://www.nokogiri.org/tutorials/searching_a_xml_html_document.html) RPath's approach. They're probably right! RPath is as much an experiment as a useful tool.
|
14
15
|
|
@@ -52,13 +53,13 @@ exp = RPath { places.place[:name] }
|
|
52
53
|
exp.eval(xml) # => "Green-Wood"
|
53
54
|
```
|
54
55
|
|
55
|
-
|
56
|
+
If we only plan to use the expression once, we can pass the graph to `RPath`. RPath evaluates the expression and returns the result:
|
56
57
|
|
57
58
|
```ruby
|
58
59
|
RPath(xml) { places.place[:name] } # => "Green-Wood"
|
59
60
|
```
|
60
61
|
|
61
|
-
|
62
|
+
Some adapters, such as the built-in Nokogiri adapter, may add convenience methods that make the syntax even prettier:
|
62
63
|
|
63
64
|
```ruby
|
64
65
|
xml.rpath { places.place[:name] } # => "Green-Wood"
|
@@ -74,11 +75,11 @@ In an RPath [graph](http://en.wikipedia.org/wiki/Graph_(mathematics)),
|
|
74
75
|
* Each vertex has zero or more named attributes, and
|
75
76
|
* Each vertex may have associated data called "content."
|
76
77
|
|
77
|
-
|
78
|
+
Adapters implement this abstraction for a particular type of graph. RPath can operate on any graph for which there is an adapter.
|
78
79
|
|
79
80
|
## Expressions
|
80
81
|
|
81
|
-
An RPath expression, given a graph,
|
82
|
+
An RPath expression, given a graph, selects a value—a vertex, a vertex array, the value of an attribute, or a vertex's content. RPath expressions are constructed by chaining methods inside the block passed to `RPath`.
|
82
83
|
|
83
84
|
### Selecting Vertices
|
84
85
|
|
@@ -202,6 +203,16 @@ xml = REXML::Document.new('<foo bar="baz"/>')
|
|
202
203
|
xml.rpath { foo['bar'] } # => "baz"
|
203
204
|
```
|
204
205
|
|
206
|
+
### Oga
|
207
|
+
|
208
|
+
RPath expressions may be evaluated on an `Oga::XML::Document` or an `Oga::XML::Element`.
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
RPath.use :oga
|
212
|
+
xml = Oga.parse_xml('<foo bar="baz"/>')
|
213
|
+
xml.rpath { foo['bar'] } # => "baz"
|
214
|
+
```
|
215
|
+
|
205
216
|
### Filesystem
|
206
217
|
|
207
218
|
The filesystem adapter exposes files and directories as vertices. Directory entries are adjacent to their directory. Expressions may be evaluated on any directory:
|
@@ -227,36 +238,44 @@ RPath('/', :filesystem) { etc.hostname.content } # => "jbook"
|
|
227
238
|
|
228
239
|
## Custom Adapters
|
229
240
|
|
230
|
-
Custom adapters
|
241
|
+
Custom adapters allow RPath expressions to operate on new types of graphs. To create a custom adapter, subclass `RPath::Adapter` and implement the abstract methods `#adjacent`, `#attribute`, `#content`, and `#name`. See the implementations in `RPath::Adapters` for examples.
|
242
|
+
|
243
|
+
Once you've implemented a custom adapter, pass an instance to `#RPath`:
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
RPath(graph, CustomAdapter.new) { foo.bar }
|
247
|
+
```
|
231
248
|
|
232
|
-
|
249
|
+
To avoid creating an instance for every evaluation, register the adapter and pass the underscored, symbolized class to `RPath`:
|
233
250
|
|
234
251
|
```ruby
|
235
|
-
RPath.use
|
252
|
+
RPath.use CustomAdapter.new
|
253
|
+
RPath(graph, :custom_adapter) { foo.bar }
|
236
254
|
```
|
237
255
|
|
238
|
-
|
256
|
+
If that's too long, pass a custom ID to `RPath.use`:
|
239
257
|
|
240
258
|
```ruby
|
241
|
-
RPath
|
259
|
+
RPath.use CustomAdapter.new, :custom
|
260
|
+
RPath(graph, :custom) { foo.bar }
|
242
261
|
```
|
243
262
|
|
244
|
-
|
263
|
+
Or, to avoid specifying the adapter altogether—as the built-in XML adapters do—implement `#adapts?` in your adapter class:
|
245
264
|
|
246
265
|
```ruby
|
247
|
-
class
|
266
|
+
class CustomAdapter < RPath::Adapter
|
248
267
|
def adapts?(graph)
|
249
|
-
graph.is_a?
|
268
|
+
graph.is_a? CustomGraph
|
250
269
|
end
|
251
|
-
...
|
270
|
+
# ...
|
252
271
|
end
|
253
272
|
```
|
254
273
|
|
255
|
-
Now RPath will select `
|
274
|
+
Now RPath will select a registered `CustomAdapter` when an expression is evaluated on a `CustomGraph`:
|
256
275
|
|
257
276
|
```ruby
|
258
|
-
RPath.use
|
259
|
-
RPath(
|
277
|
+
RPath.use CustomAdapter.new
|
278
|
+
RPath(CustomGraph.new) { foo.bar }
|
260
279
|
```
|
261
280
|
|
262
281
|
## Contributing
|
data/lib/rpath/adapters.rb
CHANGED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'oga'
|
2
|
+
|
3
|
+
module RPath
|
4
|
+
module Adapters
|
5
|
+
|
6
|
+
class Oga < RPath::Adapter
|
7
|
+
|
8
|
+
# Returns +true+ iff +graph+ is an Oga::XML::Document or an Oga::XML::Element
|
9
|
+
# @param [Object] graph
|
10
|
+
# @return [Boolean]
|
11
|
+
def adapts?(graph)
|
12
|
+
graph.is_a?(::Oga::XML::Element) || graph.is_a?(::Oga::XML::Document)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the name of the given node
|
16
|
+
# @param [Oga::XML::Document, Oga::XML::Element] vertex
|
17
|
+
# @return [String]
|
18
|
+
def name(vertex)
|
19
|
+
vertex.is_a?(::Oga::XML::Element) ? vertex.name : nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the child elements of the given node
|
23
|
+
# @param [Oga::XML::Document, Oga::XML::Element] vertex
|
24
|
+
# @return [Array<Oga::XML::Element>]
|
25
|
+
def adjacent(vertex)
|
26
|
+
vertex.children.select { |child| child.is_a?(::Oga::XML::Element) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the value of the named attribute on the given node.
|
30
|
+
# @param [Oga::XML::Document, Oga::XML::Element] vertex
|
31
|
+
# @param [String, Symbol] name
|
32
|
+
# @return [String, nil]
|
33
|
+
def attribute(vertex, name)
|
34
|
+
if vertex.is_a?(::Oga::XML::Element)
|
35
|
+
attr = vertex.attr(name)
|
36
|
+
attr && attr.value
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the text content of the given node.
|
43
|
+
# @param [Oga::XML::Document, Oga::XML::Element] vertex
|
44
|
+
# @return [String, nil]
|
45
|
+
def content(vertex)
|
46
|
+
vertex.is_a?(::Oga::XML::Element) ? vertex.text : nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Oga::XML::Document
|
54
|
+
# Evaluates an RPath expression on the document
|
55
|
+
# @example
|
56
|
+
# RPath.use :oga
|
57
|
+
# xml = Oga.parse_xml('<foo bar="baz"/>')
|
58
|
+
# xml.rpath { foo['bar'] } # => "baz"
|
59
|
+
# @see #RPath
|
60
|
+
# @return [Object]
|
61
|
+
#
|
62
|
+
def rpath(&block)
|
63
|
+
RPath self, :oga, &block
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Oga::XML::Element
|
68
|
+
# Evaluates an RPath expression on the element
|
69
|
+
# @example
|
70
|
+
# RPath.use :oga
|
71
|
+
# xml = Oga.parse_xml('<foo><bar baz="qux"/></foo>')
|
72
|
+
# xml.children.first.rpath { bar['baz'] } # => "qux"
|
73
|
+
# @see #RPath
|
74
|
+
# @return [Object]
|
75
|
+
#
|
76
|
+
def rpath(&block)
|
77
|
+
RPath self, :oga, &block
|
78
|
+
end
|
79
|
+
end
|
data/lib/rpath/expressions.rb
CHANGED
@@ -14,7 +14,7 @@ module RPath
|
|
14
14
|
# @return [Object]
|
15
15
|
# @raise [RuntimeError]
|
16
16
|
# The adapter can't be determined
|
17
|
-
# @
|
17
|
+
# @raise [ArgumentError]
|
18
18
|
# +adapter+ is not an {Adapter}, Symbol, or nil
|
19
19
|
# @see #RPath
|
20
20
|
# @see RPath.use
|
@@ -24,7 +24,7 @@ module RPath
|
|
24
24
|
when RPath::Adapter
|
25
25
|
adapter
|
26
26
|
when Symbol
|
27
|
-
Registry.find adapter
|
27
|
+
Registry.find adapter
|
28
28
|
when nil
|
29
29
|
Registry.infer graph
|
30
30
|
else
|
data/lib/rpath/version.rb
CHANGED
metadata
CHANGED
@@ -1,69 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rpath
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonah Burke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.6.0
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.6.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.7'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: oga
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.2.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - ~>
|
59
|
+
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
61
|
version: '10.0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - ~>
|
66
|
+
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '10.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: yard
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- - ~>
|
73
|
+
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
75
|
version: 0.8.7
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- - ~>
|
80
|
+
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: 0.8.7
|
69
83
|
description:
|
@@ -73,6 +87,7 @@ executables: []
|
|
73
87
|
extensions: []
|
74
88
|
extra_rdoc_files: []
|
75
89
|
files:
|
90
|
+
- ".yardopts"
|
76
91
|
- LICENSE.txt
|
77
92
|
- README.md
|
78
93
|
- lib/rpath.rb
|
@@ -80,6 +95,7 @@ files:
|
|
80
95
|
- lib/rpath/adapters.rb
|
81
96
|
- lib/rpath/adapters/filesystem.rb
|
82
97
|
- lib/rpath/adapters/nokogiri.rb
|
98
|
+
- lib/rpath/adapters/oga.rb
|
83
99
|
- lib/rpath/adapters/rexml.rb
|
84
100
|
- lib/rpath/expressions.rb
|
85
101
|
- lib/rpath/registry.rb
|
@@ -95,12 +111,12 @@ require_paths:
|
|
95
111
|
- lib
|
96
112
|
required_ruby_version: !ruby/object:Gem::Requirement
|
97
113
|
requirements:
|
98
|
-
- -
|
114
|
+
- - ">="
|
99
115
|
- !ruby/object:Gem::Version
|
100
116
|
version: 1.9.3
|
101
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
118
|
requirements:
|
103
|
-
- -
|
119
|
+
- - ">="
|
104
120
|
- !ruby/object:Gem::Version
|
105
121
|
version: '0'
|
106
122
|
requirements: []
|
@@ -108,6 +124,6 @@ rubyforge_project:
|
|
108
124
|
rubygems_version: 2.4.5
|
109
125
|
signing_key:
|
110
126
|
specification_version: 4
|
111
|
-
summary:
|
127
|
+
summary: Query XML with just Ruby
|
112
128
|
test_files: []
|
113
129
|
has_rdoc:
|