Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/ox #74

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@ parser.parse("<tag>This is the contents</tag>")
# => { 'tag' => 'This is the contents' }
```

Nori supports pluggable parsers and ships with both REXML and Nokogiri implementations.
Nori supports pluggable parsers and ships with REXML, Nokogiri, and Ox implementations.
It defaults to Nokogiri since v2.0.0, but you can change it to use REXML via:

``` ruby
Nori.new(:parser => :rexml) # or :nokogiri
```

Make sure Nokogiri is in your LOAD_PATH when parsing XML, because Nori tries to load it
or to Ox via:

``` ruby
Nori.new(:parser => :ox)
```

Make sure Nokogiri or Ox is in your LOAD_PATH when parsing XML, because Nori tries to load it
when it's needed.


Expand Down
2 changes: 1 addition & 1 deletion lib/nori.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def self.hash_key(name, options = {})
name
end

PARSERS = { :rexml => "REXML", :nokogiri => "Nokogiri" }
PARSERS = { :rexml => "REXML", :nokogiri => "Nokogiri", :ox => "Ox" }

def initialize(options = {})
defaults = {
Expand Down
74 changes: 74 additions & 0 deletions lib/nori/parser/ox.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require "ox"

class Nori
module Parser

# = Ox::Parser::Ox
#
# Ox SAX parser.
module Ox

class Document < ::Ox::Sax
attr_accessor :options
attr_accessor :element_name

def stack
@stack ||= []
end

def attr_stack
@attr_stack ||= {}
end

def start_element(name, attrs = [])
@element_name = name.to_s
attr_stack.clear
end

# To keep backward behaviour compatibility
# delete last child if it is a space-only text node
def end_element(name)
if stack.size > 1
last = stack.pop
maybe_string = last.children.last
if maybe_string.is_a?(String) and maybe_string.strip.empty?
last.children.pop
end
stack.last.add_node last
end
end

# If this node is a successive character then add it as is.
# First child being a space-only text node will not be added
# because there is no previous characters.
def characters(string)
last = stack.last
if last and last.children.last.is_a?(String) or string.strip.size > 0
last.add_node(string)
end
end

alias text characters
alias cdata characters

def attr(name, str)
attr_stack[name.to_s] = str
end

def attrs_done
return if element_name.nil?
stack.push Nori::XMLUtilityNode.new(options, element_name, Hash[*attr_stack.flatten])
end

end

def self.parse(xml, options)
document = Document.new
document.options = options
::Ox.sax_parse document, xml
document.stack.length > 0 ? document.stack.pop.to_hash : {}
end

end
end
end
3 changes: 2 additions & 1 deletion nori.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Gem::Specification.new do |s|
s.add_development_dependency "rake", "~> 10.0"
s.add_development_dependency "nokogiri", ">= 1.4.0"
s.add_development_dependency "rspec", "~> 2.12"

s.add_development_dependency "ox", "~> 2.3"

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
Expand Down
2 changes: 1 addition & 1 deletion spec/nori/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

describe "PARSERS" do
it "should return a Hash of parser details" do
expect(Nori::PARSERS).to eq({ :rexml => "REXML", :nokogiri => "Nokogiri" })
expect(Nori::PARSERS).to eq({ :rexml => "REXML", :nokogiri => "Nokogiri", :ox => "Ox" })
end
end

Expand Down
4 changes: 2 additions & 2 deletions spec/nori/core_ext/object_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
describe "#blank?" do
[nil, false, [], {}].each do |object|
it "should return true for: #{object.inspect}" do
expect(object.blank?).to be_true
expect(object.blank?).to be_truthy
end
end

[true, [nil], 1, "string", { :key => "value" }].each do |object|
it "should return false for: #{object.inspect}" do
expect(object.blank?).to be_false
expect(object.blank?).to be_falsey
end
end
end
Expand Down