Welcome to the "trac"-ing site of soap4r!
[soap4r] [httpclient] [openpgp4u] [pkcs1] [logger] [csv] [vtr]

root/branches/1_5/lib/wsdl/xmlSchema/parser.rb

Revision 1824, 3.9 kB (checked in by nahi, 2 years ago)
  • Copyright notice updated. add '2000-2007' uniformly.
  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1 # WSDL4R - WSDL XML Instance parser library.
2 # Copyright (C) 2000-2007  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
76       parent = lastframe.node
77     else
78       ns = XSD::NS.new
79       parent = nil
80     end
81     # ns might be the same
82     ns, attrs = XSD::XMLParser.filter_ns(ns, attrs)
83     node = decode_tag(ns, name, attrs, parent)
84     @parsestack << ParseFrame.new(ns, name, node)
85   end
86
87   def characters(text)
88     lastframe = @parsestack.last
89     if lastframe
90       # Need not to be cloned because character does not have attr.
91       ns = lastframe.ns
92       decode_text(ns, text)
93     else
94       p text if $DEBUG
95     end
96   end
97
98   def end_element(name)
99     lastframe = @parsestack.pop
100     unless name == lastframe.name
101       raise UnexpectedElementError.new("closing element name '#{name}' does not match with opening element '#{lastframe.name}'")
102     end
103     decode_tag_end(lastframe.ns, lastframe.node)
104     @lastnode = lastframe.node
105   end
106
107 private
108
109   def decode_tag(ns, name, attrs, parent)
110     o = nil
111     elename = ns.parse(name)
112     if !parent
113       if elename == SchemaName
114         o = Schema.parse_element(elename)
115         o.location = @location
116       else
117         raise UnknownElementError.new("unknown element: #{elename}")
118       end
119       o.root = @originalroot if @originalroot   # o.root = o otherwise
120     else
121       if elename == AnnotationName
122         # only the first annotation element is allowed for each element.
123         o = Annotation.new
124       else
125         o = parent.parse_element(elename)
126       end
127       if o.nil?
128         unless @ignored.key?(elename)
129           warn("ignored element: #{elename} of #{parent.class}")
130           @ignored[elename] = elename
131         end
132         o = Documentation.new   # which accepts any element.
133       end
134       # node could be a pseudo element.  pseudo element has its own parent.
135       o.root = parent.root
136       o.parent = parent if o.parent.nil?
137     end
138     attrs.each do |key, value|
139       attr_ele = ns.parse(key, true)
140       value_ele = ns.parse(value, false)
141       value_ele.source = value  # for recovery; value may not be a QName
142       if attr_ele == IdAttrName
143         o.id = value_ele
144       else
145         if o.parse_attr(attr_ele, value_ele).nil?
146           unless @ignored.key?(attr_ele)
147             warn("ignored attr: #{attr_ele}")
148             @ignored[attr_ele] = attr_ele
149           end
150         end
151       end
152     end
153     o
154   end
155
156   def decode_tag_end(ns, node)
157     node.parse_epilogue
158   end
159
160   def decode_text(ns, text)
161     @textbuf << text
162   end
163 end
164
165
166 end
167 end
Note: See TracBrowser for help on using the browser.