rasantiago-tiny_xpath_helper 0.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.
- data/README.rdoc +48 -0
- data/Rakefile +23 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/tiny_xpath_helper.rb +97 -0
- data/tasks/tiny_xpath_helper_tasks.rake +4 -0
- data/test/test_helper.rb +5 -0
- data/test/tiny_xpath_helper_test.rb +8 -0
- data/test/xml/sample.xml +9 -0
- data/tiny_xpath_helper.gemspec +19 -0
- data/uninstall.rb +1 -0
- metadata +65 -0
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= TinyXPathHelper
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
Very light syntax for using XPaths on XML documents or REXML nodes
|
6
|
+
|
7
|
+
== Examples
|
8
|
+
|
9
|
+
TinyXPathHelper.new takes one parameter: an XML document (as a string or IO) or a REXML element
|
10
|
+
>> xpath = TinyXPathHelper.new( File.open( 'test/xml/sample.xml' ) )
|
11
|
+
|
12
|
+
Then, to find the string values of matching nodes, there's a super-light syntax:
|
13
|
+
>> xpath[ 'node/' ]
|
14
|
+
=> ["one", "two", "three\n "]
|
15
|
+
|
16
|
+
It works on attributes, too
|
17
|
+
>> xpath[ 'node/@style' ]
|
18
|
+
=> ["first"]
|
19
|
+
|
20
|
+
If you prefer, you can use #all instead of square brackets
|
21
|
+
>> xpath.all( 'node/@style' )
|
22
|
+
=> ["first"]
|
23
|
+
|
24
|
+
If you just want the first match, use #first
|
25
|
+
>> xpath.first( 'node/' )
|
26
|
+
=> "one"
|
27
|
+
|
28
|
+
A slightly more elaborate API is available as #find_xpath
|
29
|
+
>> xpath.find_xpath( 'node/@style', :format => :xml, :find => :first )
|
30
|
+
=> style='first'
|
31
|
+
|
32
|
+
Where :format can be :text (returns a string), or :xml (returns a REXML element),
|
33
|
+
and :find can be :first or :all
|
34
|
+
|
35
|
+
>> xpath.find_xpath( 'node/@style', :format => :xml, :find => :all )
|
36
|
+
=> [style='first']
|
37
|
+
|
38
|
+
The output from :format => :xml is suitable for passing to another TinyXPathHelper
|
39
|
+
>> node_tree = xpath.find_xpath( 'node/three', :format => :xml )
|
40
|
+
>> deeper_xpath = TinyXPathHelper.new( node_tree )
|
41
|
+
>> deeper_xpath[ 'b/@beta' ]
|
42
|
+
=> ["true"]
|
43
|
+
|
44
|
+
--
|
45
|
+
doctest_require: 'lib/tiny_xpath_helper.rb'
|
46
|
+
++
|
47
|
+
|
48
|
+
Copyright (c) 2009 raSANTIAGO + Associates LLC
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the tiny_xpath_helper plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the tiny_xpath_helper plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'TinyXPathHelper'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "lib", "tiny_path_helper")
|
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
class TinyXPathHelper
|
4
|
+
attr :node
|
5
|
+
|
6
|
+
def initialize(xml)
|
7
|
+
@xml = xml
|
8
|
+
@node = self.class.xml_node_for_xmlish(xml)
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_xpath(xpath_expr, options = {})
|
12
|
+
self.class.find_xpath_from( node, xpath_expr, options )
|
13
|
+
end
|
14
|
+
|
15
|
+
alias at find_xpath
|
16
|
+
|
17
|
+
def first(xpath_expr, options = {})
|
18
|
+
self.find_xpath( xpath_expr, options.update(:find => :first) )
|
19
|
+
end
|
20
|
+
|
21
|
+
def all(xpath_expr, options = {})
|
22
|
+
self.find_xpath( xpath_expr, options.update(:find => :all) )
|
23
|
+
end
|
24
|
+
alias [] all
|
25
|
+
|
26
|
+
def self.io_stream_classes
|
27
|
+
[ IOStream ] rescue [ IO, StringIO ] # thoughtbot-paperclip fixes the ducktype mess here
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.classes_that_are_xmlish
|
31
|
+
io_stream_classes + [ String, REXML::Document ]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.xml_node_for_xmlish( xml )
|
35
|
+
if io_stream_classes.any?{|k| k === xml }
|
36
|
+
xml = xml.read
|
37
|
+
end
|
38
|
+
if String === xml
|
39
|
+
xml = REXML::Document.new(xml)
|
40
|
+
end
|
41
|
+
if REXML::Document === xml
|
42
|
+
xml = xml.root
|
43
|
+
end
|
44
|
+
if not REXML::Element === xml
|
45
|
+
raise TypeError.new("Expected REXML::Element, got #{xml.class}")
|
46
|
+
end
|
47
|
+
return xml
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.xml_node_to_text(node)
|
51
|
+
if(node.respond_to? :text)
|
52
|
+
# XML::Elements don't to_s in the way we want
|
53
|
+
val = node.text
|
54
|
+
else
|
55
|
+
val = node.to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.find_xpath_from(element, path, options = {}, &blk)
|
60
|
+
|
61
|
+
format = options[:format] || :text
|
62
|
+
if format == :array
|
63
|
+
options.update( :format => :text, :find => :all )
|
64
|
+
end
|
65
|
+
|
66
|
+
count = options[:find] || :first
|
67
|
+
|
68
|
+
if format == :text
|
69
|
+
filter = lambda{|node| node && xml_node_to_text(node) }
|
70
|
+
elsif format == :xml
|
71
|
+
filter = lambda{|node| node }
|
72
|
+
else
|
73
|
+
raise "I don't know the format #{format.inspect}"
|
74
|
+
end
|
75
|
+
|
76
|
+
if count == :all
|
77
|
+
val = REXML::XPath.match(element, path).map do |node|
|
78
|
+
filter.call( node )
|
79
|
+
end
|
80
|
+
elsif count == :first
|
81
|
+
val = filter.call(
|
82
|
+
REXML::XPath.first(element, path)
|
83
|
+
)
|
84
|
+
else
|
85
|
+
raise "I don't know how to find #{count.inspect}"
|
86
|
+
end
|
87
|
+
|
88
|
+
if(blk)
|
89
|
+
return val if val == nil or val == []
|
90
|
+
return blk.call(val)
|
91
|
+
end
|
92
|
+
return val
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
TinyXpathHelper = TinyXPathHelper
|
data/test/test_helper.rb
ADDED
data/test/xml/sample.xml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{tiny_xpath_helper}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.authors = ["Jesse Wolfe"]
|
8
|
+
s.date = %q{2009-06-01}
|
9
|
+
s.description = %q{Very light syntax for using XPaths on XML documents or REXML nodes}
|
10
|
+
s.email = %q{jesse@rasantiago.com}
|
11
|
+
s.files = %w[ uninstall.rb init.rb Rakefile lib/tiny_xpath_helper.rb tiny_xpath_helper.gemspec README.rdoc tasks/tiny_xpath_helper_tasks.rake install.rb test/tiny_xpath_helper_test.rb test/xml test/xml/sample.xml test/test_helper.rb ]
|
12
|
+
s.has_rdoc = false
|
13
|
+
s.homepage = %q{http://github.com/rasantiago/tiny_xpath_helper}
|
14
|
+
s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.rubygems_version = %q{1.3.1}
|
17
|
+
s.summary = %q{Very light syntax for using XPaths on XML documents or REXML nodes}
|
18
|
+
end
|
19
|
+
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rasantiago-tiny_xpath_helper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jesse Wolfe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-01 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Very light syntax for using XPaths on XML documents or REXML nodes
|
17
|
+
email: jesse@rasantiago.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- uninstall.rb
|
26
|
+
- init.rb
|
27
|
+
- Rakefile
|
28
|
+
- lib/tiny_xpath_helper.rb
|
29
|
+
- tiny_xpath_helper.gemspec
|
30
|
+
- README.rdoc
|
31
|
+
- tasks/tiny_xpath_helper_tasks.rake
|
32
|
+
- install.rb
|
33
|
+
- test/tiny_xpath_helper_test.rb
|
34
|
+
- test/xml
|
35
|
+
- test/xml/sample.xml
|
36
|
+
- test/test_helper.rb
|
37
|
+
has_rdoc: false
|
38
|
+
homepage: http://github.com/rasantiago/tiny_xpath_helper
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --inline-source
|
42
|
+
- --charset=UTF-8
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.2.0
|
61
|
+
signing_key:
|
62
|
+
specification_version: 2
|
63
|
+
summary: Very light syntax for using XPaths on XML documents or REXML nodes
|
64
|
+
test_files: []
|
65
|
+
|