rpath 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/rpath.svg)](http://badge.fury.io/rb/rpath)
|
6
|
+
[![Build Status](https://travis-ci.org/jonahb/rpath.svg?branch=master)](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:
|