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

root/trunk/lib/wsdl/parser.rb

Revision 1898, 3.9 kB (checked in by nahi, 1 year ago)
  • add :default_ns_tag option to configure a pre-defined Namespace tag.

:default_ns : to configure namespace definitions at SOAPEnvelope.
:default_ns_tag: to configure pre-defined namespace tag.

closes #383.

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