Skip to content

Commit 3cfd053

Browse files
authored
Add Nokogiri XML parser (#55)
This one is similar to the LibXML parser, but uses the Nokogiri SAX parser under the hood. This library is already used in a lot of web projects and is easier to install in Windows than LibXML. There is no direct dependency on the nokogiri gem, if the gem is not available the code will only error in case it is used. Unfortunately, I could not find a way to enable the gem in the CI for the Windows tasks. It passes on the regular Windows runners, but fails on mingw/mswin, and I could not find a way to separate those two. If someone knows how to fix that, or how to install/compile Nokogiri on the latter two platforms, please go ahead and fix it. This has been suggested/requested in https://bugs.ruby-lang.org/issues/9379, all the way back in 2014. --------- Co-authored-by: Herwin <herwinw@users.noreply.github.com>
1 parent f27d017 commit 3cfd053

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ gemspec
55
group :development do
66
gem "bundler"
77
gem "libxml-ruby", platforms: [:ruby, :jruby]
8+
gem "nokogiri", platforms: [:ruby, :jruby]
89
gem "rake"
910
gem "test-unit"
1011
end

lib/xmlrpc.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@
5959
# * libxml (LibXMLStreamParser)
6060
# * Compiled
6161
# * See https://rubygems.org/gems/libxml-ruby/
62+
# * nokogiri (NokogiriStreamParser)
63+
# * Compiled
64+
# * See https://nokogiri.org
6265
#
6366
# * General
64-
# * possible to choose between XMLParser module (Expat wrapper) and REXML (pure Ruby) parsers
67+
# * possible to choose between REXML (pure Ruby) and LibXML/Nokogiri (compiled) parsers
6568
# * Marshalling Ruby objects to Hashes and reconstruct them later from a Hash
6669
# * SandStorm component architecture XMLRPC::Client interface
6770
#

lib/xmlrpc/config.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module Config
1515
#
1616
# * XMLParser::REXMLStreamParser
1717
# * XMLParser::LibXMLStreamParser
18+
# * XMLParser::NokogiriStreamParser
1819
DEFAULT_PARSER = XMLParser::REXMLStreamParser
1920

2021
# enable <code><nil/></code> tag

lib/xmlrpc/parser.rb

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,51 @@ def parse(str)
624624
end
625625
end
626626

627-
Classes = [REXMLStreamParser, LibXMLStreamParser]
627+
class NokogiriStreamParser < AbstractStreamParser
628+
def initialize
629+
require 'nokogiri'
630+
@parser_class = NokogiriStreamListener
631+
end
632+
633+
class NokogiriStreamListener
634+
include StreamParserMixin
635+
636+
def self.handler
637+
# We need to construct this on first use, since we cannot be sure Nokogiri is available
638+
@handler ||= begin
639+
Class.new(Nokogiri::XML::SAX::Document) do
640+
def initialize(parent)
641+
super()
642+
@parent = parent
643+
end
644+
645+
def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = [])
646+
@parent.startElement(name, attrs)
647+
end
648+
649+
def end_element_namespace(name, prefix = nil, uri = nil)
650+
@parent.endElement(name)
651+
end
652+
653+
def characters(string)
654+
@parent.character(string)
655+
end
656+
657+
def cdata_block(string)
658+
@parent.character(string)
659+
end
660+
end
661+
end
662+
end
663+
664+
def parse(str)
665+
parser = Nokogiri::XML::SAX::Parser.new(self.class.handler.new(self))
666+
parser.parse(str)
667+
end
668+
end
669+
end
670+
671+
Classes = [REXMLStreamParser, LibXMLStreamParser, NokogiriStreamParser]
628672

629673
# yields an instance of each installed parser
630674
def self.each_installed_parser

0 commit comments

Comments
 (0)