[フレーム]
Last Updated: May 11, 2020
·
961
· brendanjcaffrey

Generic XML Parsing in RubyMotion With NSXMLParser

I've been working a lot with NSXMLParser objects returned by AFMotion lately, and I couldn't find too much about how to use its delegate style of parsing. I figured I'd share the love with this generic parser. It doesn't take into account namespaces or anything, but this is a good simple base if you need one.

class XMLParserDelegate
 attr_reader :root

 def initialize
 @root = nil
 @queue = []
 end

 def parser(parser, didStartElement:elementName, namespaceURI:namespaceURI, qualifiedName:qualifiedName, attributes:attributeDict)
 el = XMLElement.new(elementName, attributeDict)

 if @queue.empty?
 @root = el 
 else
 @queue[-1].add_child(el)
 end

 @queue << el
 end

 def parser(parser, didEndElement:elementName, namespaceURI:namespaceURI, qualifiedName:qName)
 @queue.pop
 end
end

class XMLElement
 attr_accessor :name, :attributes, :children

 def initialize(name, attributes)
 @el = name
 @attributes = attributes
 @children = []
 end

 def add_child(el)
 @children << el
 end

 def to_xml
 if @children.empty?
 '<' + @el + attrs_as_xml + '/>'
 else
 '<' + @el + attrs_as_xml + '>' + @children.map(&:to_xml).join + '</' + @el + '>'
 end
 end

 private
 def attrs_as_xml
 @attributes.map { |k, v| ' ' + k.to_s + '="' + v.to_s + '"' }.join
 end
end

Used like this (for example on the REPL):

(main)> AFMotion::XML.get('http://example.com/test.xml') do |result|
 parser = result.object
end
=> #<AFXMLRequestOperation:0xa0d6490>
(main)> parser.delegate = XMLParserDelegate.new
=> #<XMLParserDelegate:0xa0d8900 @root=nil @queue=[]>
(main)> parser.parse
=> 1
(main)> parser.delegate.root
=> #<XMLElement:....>

There are plenty of other NSXMLParserDelegate callbacks to check out, so take a look.

AltStyle によって変換されたページ (->オリジナル) /