PageRenderTime 118ms CodeModel.GetById 104ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 1ms

/tools/Ruby/lib/ruby/1.8/wsdl/xmlSchema/parser.rb

http://github.com/agross/netopenspace
Ruby | 166 lines | 133 code | 25 blank | 8 comment | 13 complexity | 60118c3ef46f03908fa5aeb984941d87 MD5 | raw file
  1# WSDL4R - WSDL XML Instance parser library.
  2# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
  3
  4# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
  5# redistribute it and/or modify it under the same terms of Ruby's license;
  6# either the dual license version in 2003, or any later version.
  7
  8
  9require 'xsd/qname'
 10require 'xsd/ns'
 11require 'xsd/charset'
 12require 'xsd/datatypes'
 13require 'xsd/xmlparser'
 14require 'wsdl/xmlSchema/data'
 15
 16
 17module WSDL
 18module XMLSchema
 19
 20
 21class Parser
 22  include XSD
 23
 24  class ParseError < Error; end
 25  class FormatDecodeError < ParseError; end
 26  class UnknownElementError < FormatDecodeError; end
 27  class UnknownAttributeError < FormatDecodeError; end
 28  class UnexpectedElementError < FormatDecodeError; end
 29  class ElementConstraintError < FormatDecodeError; end
 30  class AttributeConstraintError < FormatDecodeError; end
 31
 32private
 33
 34  class ParseFrame
 35    attr_reader :ns
 36    attr_reader :name
 37    attr_accessor :node
 38
 39  private
 40
 41    def initialize(ns, name, node)
 42      @ns = ns
 43      @name = name
 44      @node = node
 45    end
 46  end
 47
 48public
 49
 50  def initialize(opt = {})
 51    @parser = XSD::XMLParser.create_parser(self, opt)
 52    @parsestack = nil
 53    @lastnode = nil
 54    @ignored = {}
 55    @location = opt[:location]
 56    @originalroot = opt[:originalroot]
 57  end
 58
 59  def parse(string_or_readable)
 60    @parsestack = []
 61    @lastnode = nil
 62    @textbuf = ''
 63    @parser.do_parse(string_or_readable)
 64    @lastnode
 65  end
 66
 67  def charset
 68    @parser.charset
 69  end
 70
 71  def start_element(name, attrs)
 72    lastframe = @parsestack.last
 73    ns = parent = nil
 74    if lastframe
 75      ns = lastframe.ns.clone_ns
 76      parent = lastframe.node
 77    else
 78      ns = XSD::NS.new
 79      parent = nil
 80    end
 81    attrs = XSD::XMLParser.filter_ns(ns, attrs)
 82    node = decode_tag(ns, name, attrs, parent)
 83    @parsestack << ParseFrame.new(ns, name, node)
 84  end
 85
 86  def characters(text)
 87    lastframe = @parsestack.last
 88    if lastframe
 89      # Need not to be cloned because character does not have attr.
 90      ns = lastframe.ns
 91      decode_text(ns, text)
 92    else
 93      p text if $DEBUG
 94    end
 95  end
 96
 97  def end_element(name)
 98    lastframe = @parsestack.pop
 99    unless name == lastframe.name
100      raise UnexpectedElementError.new("closing element name '#{name}' does not match with opening element '#{lastframe.name}'")
101    end
102    decode_tag_end(lastframe.ns, lastframe.node)
103    @lastnode = lastframe.node
104  end
105
106private
107
108  def decode_tag(ns, name, attrs, parent)
109    o = nil
110    elename = ns.parse(name)
111    if !parent
112      if elename == SchemaName
113	o = Schema.parse_element(elename)
114        o.location = @location
115      else
116	raise UnknownElementError.new("unknown element: #{elename}")
117      end
118      o.root = @originalroot if @originalroot   # o.root = o otherwise
119    else
120      if elename == AnnotationName
121        # only the first annotation element is allowed for each element.
122        o = Annotation.new
123      else
124        o = parent.parse_element(elename)
125      end
126      unless o
127        unless @ignored.key?(elename)
128          warn("ignored element: #{elename} of #{parent.class}")
129          @ignored[elename] = elename
130        end
131	o = Documentation.new	# which accepts any element.
132      end
133      # node could be a pseudo element.  pseudo element has its own parent.
134      o.root = parent.root
135      o.parent = parent if o.parent.nil?
136    end
137    attrs.each do |key, value|
138      attr_ele = ns.parse(key, true)
139      value_ele = ns.parse(value, true)
140      value_ele.source = value  # for recovery; value may not be a QName
141      if attr_ele == IdAttrName
142	o.id = value_ele
143      else
144        unless o.parse_attr(attr_ele, value_ele)
145          unless @ignored.key?(attr_ele)
146            warn("ignored attr: #{attr_ele}")
147            @ignored[attr_ele] = attr_ele
148          end
149        end
150      end
151    end
152    o
153  end
154
155  def decode_tag_end(ns, node)
156    node.parse_epilogue
157  end
158
159  def decode_text(ns, text)
160    @textbuf << text
161  end
162end
163
164
165end
166end