Skip to content

Commit 29c145b

Browse files
committed
Implement error handling in Nokogiri parser
If a parse error occurred anywhere inside the XML, the Nokogiri parser just returns whatever happens to be on top of the stack. This makes it very hard to troubleshoot the error down the line. To avoid this we need to implement the `error` method and raise an error. This introduces a new exception type Nori::ParseError which we also need to raise in the REXML parser to make it symmetric.
1 parent dbbd948 commit 29c145b

File tree

4 files changed

+15
-1
lines changed

4 files changed

+15
-1
lines changed

lib/nori.rb

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require "nori/xml_utility_node"
44

55
class Nori
6+
class ParseError < StandardError; end
67

78
def self.hash_key(name, options = {})
89
name = name.tr("-", "_") if options[:convert_dashes_to_underscores]

lib/nori/parser/nokogiri.rb

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Nokogiri
1010

1111
class Document < ::Nokogiri::XML::SAX::Document
1212
attr_accessor :options
13+
attr_accessor :last_error
1314

1415
def stack
1516
@stack ||= []
@@ -44,13 +45,17 @@ def characters(string)
4445

4546
alias cdata_block characters
4647

48+
def error(message)
49+
@last_error = message
50+
end
4751
end
4852

4953
def self.parse(xml, options)
5054
document = Document.new
5155
document.options = options
5256
parser = ::Nokogiri::XML::SAX::Parser.new document
5357
parser.parse xml
58+
raise ParseError, document.last_error if document.last_error
5459
document.stack.length > 0 ? document.stack.pop.to_hash : {}
5560
end
5661

lib/nori/parser/rexml.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ def self.parse(xml, options)
1515
parser = ::REXML::Parsers::BaseParser.new(xml)
1616

1717
while true
18-
raw_data = parser.pull
18+
begin
19+
raw_data = parser.pull
20+
rescue ::REXML::ParseException => error
21+
raise Nori::ParseError, error.message
22+
end
1923
event = unnormalize(raw_data)
2024
case event[0]
2125
when :end_document

spec/nori/nori_spec.rb

+4
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,10 @@
640640
expect(parse(' ')).to eq({})
641641
end
642642

643+
it "raises error on missing end tag" do
644+
expect { parse('<foo><bar>foo bar</foo>') }.to raise_error(Nori::ParseError)
645+
end
646+
643647
end
644648
end
645649

0 commit comments

Comments
 (0)