Skip to content

Commit 9dd2a4d

Browse files
committed
Improve REXMLX support and use different Gemfiles for pure vs. compiled (REXML vs Nokogiri).
WITH_NOKOGIRI environment variable now seemingly ignored when doing `bundle install`. This addresses issue #29.
1 parent 5c77a4c commit 9dd2a4d

15 files changed

Lines changed: 204 additions & 77 deletions

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
/user-test-cases
66
/.rbx/
77
/spec/w3c-rdf
8-
Gemfile.lock
8+
*.lock

.travis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ rvm:
99
- 2.1
1010
- jruby-19mode
1111
- rbx-2
12+
gemfile:
13+
- Gemfile
14+
- Gemfile-pure
1215
env:
1316
global:
1417
- CI=true
15-
matrix:
16-
- WITH_NOKOGIRI=true
17-
- WITH_NOKOGIRI=false
1818
cache: bundler

Gemfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ gemspec
44

55
gem "rdf", :git => "git://github.com/ruby-rdf/rdf.git", :branch => "develop"
66
gem "rdf-rdfa", :git => "git://github.com/ruby-rdf/rdf-rdfa.git", :branch => "develop"
7-
gem "nokogiri" unless ENV["WITH_NOKOGIRI"] == "false"
7+
gem "nokogiri"
88

99
group :development do
10+
gem "equivalent-xml"
1011
gem "rdf-xsd", :git => "git://github.com/ruby-rdf/rdf-xsd.git", :branch => "develop"
1112
gem 'json-ld', :git => "git://github.com/ruby-rdf/json-ld.git", :branch => "develop"
1213
gem 'rdf-isomorphic', :git => "git://github.com/ruby-rdf/rdf-isomorphic.git", :branch => "develop"

Gemfile-pure

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# "Pure" version of Gemfile, without C bindings
2+
source "https://rubygems.org"
3+
4+
gemspec
5+
6+
gem "rdf", :git => "git://github.com/ruby-rdf/rdf.git", :branch => "develop"
7+
gem "rdf-rdfa", :git => "git://github.com/ruby-rdf/rdf-rdfa.git", :branch => "develop"
8+
9+
group :development do
10+
gem "rdf-xsd", :git => "git://github.com/ruby-rdf/rdf-xsd.git", :branch => "develop"
11+
gem 'json-ld', :git => "git://github.com/ruby-rdf/json-ld.git", :branch => "develop"
12+
gem 'rdf-isomorphic', :git => "git://github.com/ruby-rdf/rdf-isomorphic.git", :branch => "develop"
13+
gem "rdf-spec", :git => "git://github.com/ruby-rdf/rdf-spec.git", :branch => "develop"
14+
gem "rdf-turtle", :git => "git://github.com/ruby-rdf/rdf-turtle.git", :branch => "develop"
15+
end
16+
17+
group :debug do
18+
gem "wirble"
19+
gem "ruby-debug", :platforms => :jruby
20+
gem "debugger", :platforms => :mri_19
21+
gem "byebug", :platforms => [:mri_20, :mri_21]
22+
end
23+
24+
platforms :rbx do
25+
gem 'rubysl', '~> 2.0'
26+
gem 'rubinius', '~> 2.0'
27+
gem 'json'
28+
end

lib/rdf/rdfxml/patches/nokogiri_hacks.rb

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@ def uri
55
ns = self.namespace ? self.namespace.href : RDF::XML.to_s
66
RDF::URI.intern(ns + self.node_name)
77
end
8-
9-
def display_path
10-
@display_path ||= case self
11-
when Nokogiri::XML::Document then ""
12-
when Nokogiri::XML::Element then parent ? "#{parent.display_path}/#{name}" : name
13-
when Nokogiri::XML::Attr then "#{parent && parent.display_path}@#{name}"
14-
end
15-
end
168

179
alias_method :attribute_with_ns_without_ffi_null, :attribute_with_ns
1810
##

lib/rdf/rdfxml/reader.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def each_statement(&block)
188188
add_debug(root, "base_uri: #{base_uri.inspect}")
189189

190190
rdf_nodes = root.xpath("//rdf:RDF", "rdf" => RDF.to_uri.to_s)
191-
if rdf_nodes.length == 0
191+
if rdf_nodes.size == 0
192192
# If none found, root element may be processed as an RDF Node
193193

194194
ec = EvaluationContext.new(base_uri, root, @graph) do |prefix, value|
@@ -207,7 +207,7 @@ def each_statement(&block)
207207
prefix(prefix, value)
208208
end
209209
node.children.each {|el|
210-
next unless el.elem?
210+
next unless el.element?
211211
raise "el must be a proxy not a #{el.class}" unless el.is_a?(@implementation::NodeProxy)
212212
new_ec = ec.clone(el) do |prefix, value|
213213
prefix(prefix, value)
@@ -316,7 +316,7 @@ def nodeElement(el, ec)
316316
li_counter = 0 # this will increase for each li we iterate through
317317
el.children.each do |child|
318318
raise "child must be a proxy not a #{child.class}" unless child.is_a?(@implementation::NodeProxy)
319-
next unless child.elem?
319+
next unless child.element?
320320
child_ec = ec.clone(child) do |prefix, value|
321321
prefix(prefix, value)
322322
end
@@ -338,7 +338,7 @@ def nodeElement(el, ec)
338338
raise "element node must be a proxy not a #{node.class}" unless node.is_a?(@implementation::NodeProxy)
339339
end
340340

341-
if element_nodes.length > 1
341+
if element_nodes.size > 1
342342
element_nodes.each do |node|
343343
add_debug(child) {" node: #{node.to_s}"}
344344
end
@@ -399,7 +399,7 @@ def nodeElement(el, ec)
399399
add_debug(child) {"nodeID: #{nodeID}"} if nodeID
400400
add_debug(child) {"id: #{id}"} if id
401401

402-
if attrs.empty? && datatype.nil? && parseType.nil? && element_nodes.length == 1
402+
if attrs.empty? && datatype.nil? && parseType.nil? && element_nodes.size == 1
403403
# Production resourcePropertyElt
404404

405405
new_ec = child_ec.clone(nil) do |prefix, value|
@@ -410,7 +410,7 @@ def nodeElement(el, ec)
410410
add_debug(child) {"resourcePropertyElt: #{node_path(new_node_element)}"}
411411
new_subject = nodeElement(new_node_element, new_ec)
412412
add_triple(child, subject, predicate, new_subject)
413-
elsif attrs.empty? && parseType.nil? && element_nodes.length == 0 && text_nodes.length > 0
413+
elsif attrs.empty? && parseType.nil? && element_nodes.size == 0 && text_nodes.size > 0
414414
# Production literalPropertyElt
415415
add_debug(child, "literalPropertyElt")
416416

@@ -448,9 +448,9 @@ def nodeElement(el, ec)
448448
# c
449449
# end-element()
450450
add_debug(child, "compose new sequence with rdf:Description")
451-
node = child.clone
452-
node.attributes.keys.each {|a| node.remove_attribute(a)}
453-
node.node_name = "Description"
451+
#child.clone
452+
#node.attributes.keys.each {|a| node.remove_attribute(a)}
453+
node = el.create_node("Description", child.children)
454454
node.add_namespace(nil, RDF.to_uri.to_s)
455455
add_debug(node) { "uri: #{node.uri}, namespace: #{node.namespace.inspect}"}
456456
new_ec = child_ec.clone(nil, :subject => n) do |prefix, value|
@@ -518,7 +518,7 @@ def nodeElement(el, ec)
518518
rescue ArgumentError => e
519519
add_error(child, e.message)
520520
end
521-
elsif text_nodes.length == 0 && element_nodes.length == 0
521+
elsif text_nodes.size == 0 && element_nodes.size == 0
522522
# Production emptyPropertyElt
523523
add_debug(child, "emptyPropertyElt")
524524

lib/rdf/rdfxml/reader/nokogiri.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ def initialize(node, parent = nil)
2323
@parent = parent
2424
end
2525

26+
# Create a new element child of an existing node
27+
def create_node(name, children)
28+
native = ::Nokogiri::XML::Element.new(name, @node)
29+
children.each do |c|
30+
native.add_child(c.node)
31+
end
32+
NodeProxy.new(native, self)
33+
end
34+
2635
##
2736
# Element language
2837
#
@@ -124,6 +133,10 @@ def xpath(*args)
124133
end
125134
end
126135

136+
def at_xpath(*args)
137+
xpath(*args).first
138+
end
139+
127140
# For jRuby, there is a bug that prevents the namespace from being set on an element
128141
if RUBY_PLATFORM == "java"
129142
def add_namespace(prefix, href)
@@ -151,6 +164,8 @@ def uri
151164
RDF::URI.intern(ns + self.node_name)
152165
end
153166

167+
def to_s; @node.to_s; end
168+
154169
##
155170
# Proxy for everything else to @node
156171
def method_missing(method, *args)

lib/rdf/rdfxml/reader/rexml.rb

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require 'htmlentities'
2+
13
module RDF::RDFXML
24
class Reader < RDF::Reader
35
##
@@ -13,6 +15,11 @@ def self.library
1315
:rexml
1416
end
1517

18+
# For Attribute namespaces
19+
Namespace = Struct.new(:href, :prefix) do
20+
def to_s; href; end
21+
end
22+
1623
# Proxy class to implement uniform element accessors
1724
class NodeProxy
1825
attr_reader :node
@@ -21,6 +28,28 @@ class NodeProxy
2128
def initialize(node, parent = nil)
2229
@node = node
2330
@parent = parent
31+
@parent = NodeProxy.new(node.parent) if @parent.nil? &&
32+
node.respond_to?(:parent) &&
33+
node.parent &&
34+
!node.parent.is_a?(::REXML::Document)
35+
end
36+
37+
# Create a new element child of an existing node
38+
def create_node(name, children)
39+
native = ::REXML::Element.new(name, @node)
40+
children.each do |c|
41+
case c.node
42+
when ::REXML::Text
43+
native.add_text(c.node)
44+
when ::REXML::Element
45+
native.add_element(c.node)
46+
when ::REXML::Comment
47+
# Skip comments
48+
else
49+
raise "Unexpected child node type: #{c.node.class}"
50+
end
51+
end
52+
NodeProxy.new(native, self)
2453
end
2554

2655
##
@@ -89,7 +118,15 @@ def namespaces
89118
end
90119
ns_decls
91120
end
92-
121+
122+
def namespace
123+
Namespace.new(@node.namespace, @node.prefix) unless @node.namespace.to_s.empty?
124+
end
125+
126+
def add_namespace(prefix, uri)
127+
prefix ? !@node.add_namespace(prefix, uri) : @node.add_namespace(uri)
128+
end
129+
93130
##
94131
# Children of this node
95132
#
@@ -124,24 +161,45 @@ def element?
124161
end
125162

126163
def attribute_nodes
127-
@attribute_nodes ||= NodeSetProxy.new(@node.children.select {|n| n.is_a?(::REXML::Attribute)}, self)
164+
attrs = @node.attributes.dup.keep_if do |name, attr|
165+
!name.start_with?('xmlns')
166+
end
167+
@attribute_nodes ||= (attrs.empty? ? attrs : NodeSetProxy.new(attrs, self))
168+
end
169+
170+
def remove_attribute(key)
171+
@node.delete_attribute(key)
128172
end
129173

130174
def xpath(*args)
131175
#NodeSetProxy.new(::REXML::XPath.match(@node, path, namespaces), self)
132176
::REXML::XPath.match(@node, *args).map do |n|
133-
# Get node ancestors
134-
parent = n.ancestors.reverse.inject(nil) do |p,node|
135-
NodeProxy.new(node, p)
136-
end
137177
NodeProxy.new(n, parent)
138178
end
139179
end
140180

141-
def elem?
181+
def at_xpath(*args)
182+
xpath(*args).first
183+
end
184+
185+
##
186+
# Node type accessors
187+
#
188+
# @return [Boolean]
189+
def text?
190+
@node.is_a?(::REXML::Text)
191+
end
192+
193+
def element?
142194
@node.is_a?(::REXML::Element)
143195
end
144196

197+
def blank?
198+
@node.is_a?(::REXML::Text) && @node.empty?
199+
end
200+
201+
def to_s; @node.to_s; end
202+
145203
##
146204
# Proxy for everything else to @node
147205
def method_missing(method, *args)
@@ -166,10 +224,22 @@ def initialize(node_set, parent)
166224
# @yield child
167225
# @yieldparam [NodeProxy]
168226
def each
169-
@node_set.each do |c|
227+
@node_set.to_a.each do |c|
170228
yield NodeProxy.new(c, parent)
171229
end
172230
end
231+
232+
##
233+
# Return selected NodeProxies based on selection
234+
#
235+
# @yield child
236+
# @yieldparam [NodeProxy]
237+
# @return [Array[NodeProxy]]
238+
def select
239+
@node_set.to_a.map {|n| NodeProxy.new(n, parent)}.select do |c|
240+
yield c
241+
end
242+
end
173243

174244
##
175245
# Proxy for everything else to @node_set

lib/rdf/rdfxml/writer.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
require 'nokogiri' # FIXME: Implement using different modules as in RDF::TriX
21
require 'rdf/rdfa'
32

43
module RDF::RDFXML

rdf-rdfxml.gemspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ Gem::Specification.new do |gem|
2626
gem.add_runtime_dependency 'rdf', '~> 1.1', '>= 1.1.6'
2727
gem.add_runtime_dependency 'rdf-rdfa', '~> 1.1', '>= 1.1.4.1'
2828
gem.add_runtime_dependency 'rdf-xsd', '~> 1.1'
29+
gem.add_runtime_dependency 'htmlentities', '~> 4.3'
2930

3031
#gem.add_development_dependency 'nokogiri' , '>= 1.6.1' # conditionally done in Gemfile
31-
gem.add_development_dependency 'equivalent-xml' , '~> 0.2'
32+
#gem.add_development_dependency 'equivalent-xml' , '~> 0.2' # conditionally done in Gemfile
3233
gem.add_development_dependency 'open-uri-cached', '~> 0.0', '>= 0.0.5'
3334
gem.add_development_dependency 'spira', '= 0.0.12'
3435
gem.add_development_dependency 'json-ld', '~> 1.1'

0 commit comments

Comments
 (0)