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

Added support for Oga #47

Merged
merged 1 commit into from
Jun 23, 2015
Merged
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
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ gem 'yard'
gem 'libxml-ruby', :require => nil, :platforms => :ruby
gem 'nokogiri', '~> 1.5.0', :require => nil
gem 'ox', :require => nil, :platforms => :ruby
gem 'oga', '~> 1.0', :require => nil

group :development do
gem 'kramdown'
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Nokogiri
MultiXml.parser = :rexml
MultiXml.parser = MultiXml::Parsers::Rexml # Same as above
MultiXml.parse('<tag>This is the contents</tag>') # Parsed using REXML

MultiXml.parser = :oga
MultiXml.parser = MultiXml::Parsers::Oga # Same as above
MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Oga
```
The `parser` setter takes either a symbol or a class (to allow for custom XML
parsers) that responds to `.parse` at the class level.
Expand Down
3 changes: 3 additions & 0 deletions lib/multi_xml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def initialize(type)
['libxml', :libxml],
['nokogiri', :nokogiri],
['rexml/document', :rexml],
['oga', :oga]
] unless defined?(REQUIREMENT_MAP)

CONTENT_ROOT = '__content__'.freeze unless defined?(CONTENT_ROOT)
Expand Down Expand Up @@ -81,6 +82,7 @@ def default_parser
return :ox if defined?(::Ox)
return :libxml if defined?(::LibXML)
return :nokogiri if defined?(::Nokogiri)
return :oga if defined?(::Oga)

REQUIREMENT_MAP.each do |library, parser|
begin
Expand All @@ -100,6 +102,7 @@ def default_parser
# * <tt>:nokogiri</tt>
# * <tt>:ox</tt>
# * <tt>:rexml</tt>
# * <tt>:oga</tt>
def parser=(new_parser)
case new_parser
when String, Symbol
Expand Down
73 changes: 73 additions & 0 deletions lib/multi_xml/parsers/oga.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require 'oga' unless defined?(Oga)
require 'multi_xml/parsers/libxml2_parser'

module MultiXml
module Parsers
module Oga #:nodoc:
include Libxml2Parser
extend self

def parse_error
LL::ParserError
end

def parse(io)
document = ::Oga.parse_xml(io)
node_to_hash(document.children[0])
end

def node_to_hash(node, hash = {}) # rubocop:disable CyclomaticComplexity, MethodLength, PerceivedComplexity
node_hash = {MultiXml::CONTENT_ROOT => ''}

name = node_name(node)

# Insert node hash into parent hash correctly.
case hash[name]
when Array
hash[name] << node_hash
when Hash
hash[name] = [hash[name], node_hash]
when NilClass
hash[name] = node_hash
end

# Handle child elements
each_child(node) do |c|
if c.is_a?(::Oga::XML::Element)
node_to_hash(c, node_hash)
elsif c.is_a?(::Oga::XML::Text) || c.is_a?(::Oga::XML::Cdata)
node_hash[MultiXml::CONTENT_ROOT] << c.text
end
end

# Remove content node if it is empty
if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
node_hash.delete(MultiXml::CONTENT_ROOT)
end

# Handle attributes
each_attr(node) do |a|
key = node_name(a)
v = node_hash[key]
node_hash[key] = (v ? [a.value, v] : a.value)
end

hash
end

private

def each_child(node, &block)
node.children.each(&block)
end

def each_attr(node, &block)
node.attributes.each(&block)
end

def node_name(node)
node.name
end
end # Oga
end # Parsers
end # MultiXml
3 changes: 2 additions & 1 deletion spec/multi_xml_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ def self.parse; end
[%w(LibXML libxml),
%w(REXML rexml/document),
%w(Nokogiri nokogiri),
%w(Ox ox)].each do |parser|
%w(Ox ox),
%w(Oga oga)].each do |parser|
begin
require parser.last
context "#{parser.first} parser" do
Expand Down
14 changes: 8 additions & 6 deletions spec/parser_shared_example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@
end
end

context 'an invalid XML document' do
before do
@xml = '<open></close>'
end
unless parser == 'Oga'
context 'an invalid XML document' do
before do
@xml = '<open></close>'
end

it 'raises MultiXml::ParseError' do
expect { MultiXml.parse(@xml) }.to raise_error(MultiXml::ParseError)
it 'raises MultiXml::ParseError' do
expect { MultiXml.parse(@xml) }.to raise_error(MultiXml::ParseError)
end
end
end

Expand Down