Class: PropertyList::XmlParser
- Inherits:
-
Object
- Object
- PropertyList::XmlParser
- Defined in:
- lib/property-list/xml_parser.rb
Instance Method Summary collapse
-
#initialize(src) ⇒ XmlParser
constructor
A new instance of XmlParser.
- #parse ⇒ Object
-
#parse_object ⇒ Object
pushes obj into stack.
- #skip_space_and_comments ⇒ Object
- #syntax_error(msg) ⇒ Object
- #tag_content(e) ⇒ Object
Constructor Details
#initialize(src) ⇒ XmlParser
Returns a new instance of XmlParser.
7 8 9 |
# File 'lib/property-list/xml_parser.rb', line 7 def initialize src @lexer = StringScanner.new src end |
Instance Method Details
#parse ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/property-list/xml_parser.rb', line 19 def parse @lexer.skip(/<\?xml\s+.*?\?>*/m) # TODO xml_encoding = xml_declaration.match(/(?:\A|\s)encoding=(?:"(.*?)"|'(.*?)')(?:\s|\Z)/) skip_space_and_comments # TODO doctype should co-exist with xml @lexer.skip(/\s*<!DOCTYPE\s+.*?>/m) skip_space_and_comments if @lexer.scan(/<plist\s*\b[^\/\>]*\/>/) skip_space_and_comments if !@lexer.eos? syntax_error "unrecognized code after plist tag end" end return end plist_open = !!@lexer.scan(/<plist\s*\b.*?(?<!\/)>/m) res = parse_object skip_space_and_comments plist_close = !!@lexer.scan(/<\/plist\s*>/m) skip_space_and_comments if !@lexer.eos? syntax_error "unrecognized code after plist tag end" end if plist_open ^ plist_close syntax_error "mismatched <plist> tag" end res end |
#parse_object ⇒ Object
pushes obj into stack
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/property-list/xml_parser.rb', line 55 def parse_object skip_space_and_comments if e = @lexer.scan(/<(true|false|array|dict|data)\s*\/>/m) case e[/\w+/] when 'true'; true when 'false'; false when 'array'; [] when 'dict'; {} else; '' # data end elsif e = @lexer.scan(/<(integer|real|string|date|data)\s*>[^<>]*<\/\1\s*>/m) tag = e[/\w+/] content = tag_content e case tag when 'integer' content.to_i when 'real' content.to_f when 'string' CGI.unescape_html content when 'date' DateTime.parse content else # data StringIO.new Base64.decode64 content end elsif e = @lexer.scan(/<array\s*>/m) res = [] until (skip_space_and_comments; @lexer.scan(/<\/array\s*>/m)) e = parse_object syntax_error 'failed to parse array element' if e.nil? res << e end res elsif e = @lexer.scan(/<dict\s*>/) res = {} until (skip_space_and_comments; @lexer.scan(/<\/dict\s*>/m)) key_tag = @lexer.scan(/<key\s*>[^<>]*<\/key\s*>/m) syntax_error 'failed to parse dict key' if !key_tag key = CGI.unescape_html tag_content key_tag value = parse_object syntax_error 'failed to parse dict value' if value.nil? res[key] = value end res else nil end end |
#skip_space_and_comments ⇒ Object
11 12 13 14 15 16 17 |
# File 'lib/property-list/xml_parser.rb', line 11 def skip_space_and_comments @lexer.skip(%r{(?: [\x0A\x0D\u2028\u2029\x09\x0B\x0C\x20]+ # newline and space | <!--(?:.*?)--> )+}mx) end |
#syntax_error(msg) ⇒ Object
114 115 116 117 118 119 |
# File 'lib/property-list/xml_parser.rb', line 114 def syntax_error msg pre = @lexer.string[0...@lexer.pos] line = pre.count("\n") + 1 col = pre.size - pre.rindex("\n") raise SyntaxError, msg + " at line: #{line} col: #{col} #{@lexer.inspect}", caller end |
#tag_content(e) ⇒ Object
110 111 112 |
# File 'lib/property-list/xml_parser.rb', line 110 def tag_content e e[(e.index('>') + 1)...(e.rindex '<')] end |