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