~ubuntu-branches/ubuntu/hardy/ruby1.8/hardy-updates

« back to all changes in this revision

Viewing changes to lib/wsdl/xmlSchema/parser.rb

  • Committer: Bazaar Package Importer
  • Author(s): akira yamada
  • Date: 2007-03-13 22:11:58 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070313221158-h3oql37brlaf2go2
Tags: 1.8.6-1
* new upstream version, 1.8.6.
* libruby1.8 conflicts with libopenssl-ruby1.8 (< 1.8.6) (closes: #410018)
* changed packaging style to cdbs from dbs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
9
require 'xsd/qname'
 
10
require 'xsd/ns'
 
11
require 'xsd/charset'
 
12
require 'xsd/datatypes'
 
13
require 'xsd/xmlparser'
 
14
require 'wsdl/xmlSchema/data'
 
15
 
 
16
 
 
17
module WSDL
 
18
module XMLSchema
 
19
 
 
20
 
 
21
class 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
 
 
32
private
 
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
 
 
48
public
 
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
 
 
106
private
 
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
 
162
end
 
163
 
 
164
 
 
165
end
 
166
end