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

root/trunk/lib/xsd/ns.rb

Revision 1975, 3.5 kB (checked in by nahi, 1 year ago)
  • XML attribute must not be affected by default namespace. closes #430.
  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1 # XSD4R - XML Schema Namespace 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/datatypes'
10
11
12 module XSD
13
14
15 class NS
16   Namespace = 'http://www.w3.org/XML/1998/namespace'
17
18   KNOWN_TAG = {
19     XSD::Namespace => 'xsd',
20     XSD::InstanceNamespace => 'xsi',
21   }
22
23   class Assigner
24     attr_reader :known_tag
25
26     def initialize(known_tag)
27       @known_tag = known_tag.dup
28       @count = 0
29     end
30
31     def assign(ns)
32       if @known_tag.key?(ns)
33         return @known_tag[ns]
34       end
35       @count += 1
36       "n#{@count}"
37     end
38   end
39
40   attr_reader :default_namespace
41
42   class FormatError < Error; end
43
44 public
45
46   def initialize(tag2ns = nil)
47     @tag2ns = tag2ns || ns_default
48     @ns2tag = @tag2ns.invert
49     @assigner = nil
50     @default_namespace = nil
51   end
52
53   def known_tag
54     @assigner ||= Assigner.new(default_known_tag)
55     @assigner.known_tag
56   end
57
58   def assign(ns, tag = nil)
59     if tag == ''
60       if ns.empty?
61         @default_namespace = nil
62       else
63         @default_namespace = ns
64       end
65       tag
66     else
67       @assigner ||= Assigner.new(default_known_tag)
68       tag ||= @assigner.assign(ns)
69       @ns2tag[ns] = tag
70       @tag2ns[tag] = ns
71       tag
72     end
73   end
74
75   def assigned?(ns)
76     @default_namespace == ns or @ns2tag.key?(ns)
77   end
78
79   def assigned_as_tagged?(ns)
80     @ns2tag.key?(ns)
81   end
82
83   def assigned_tag?(tag)
84     @tag2ns.key?(tag)
85   end
86
87   def clone_ns
88     cloned = self.class.new(@tag2ns.dup)
89     cloned.assigner = @assigner
90     cloned.assign(@default_namespace, '') if @default_namespace
91     cloned
92   end
93
94   def name(qname)
95     if qname.namespace == @default_namespace
96       qname.name
97     elsif tag = @ns2tag[qname.namespace]
98       "#{tag}:#{qname.name}"
99     else
100       raise FormatError.new("namespace: #{qname.namespace} not defined yet")
101     end
102   end
103
104   # no default namespace
105   def name_attr(qname)
106     if tag = @ns2tag[qname.namespace]
107       "#{tag}:#{qname.name}"
108     else
109       raise FormatError.new("namespace: #{qname.namespace} not defined yet")
110     end
111   end
112
113   def compare(ns, name, rhs)
114     if (ns == @default_namespace)
115       return true if (name == rhs)
116     end
117     @tag2ns.each do |assigned_tag, assigned_ns|
118       if assigned_ns == ns && "#{assigned_tag}:#{name}" == rhs
119         return true
120       end
121     end
122     false
123   end
124
125   # $1 and $2 are necessary.
126   ParseRegexp = Regexp.new('\A([^:]+)(?::(.+))?\z', nil, 'NONE')
127
128   def parse(str, local = false)
129     if ParseRegexp =~ str
130       if (name = $2) and (ns = @tag2ns[$1])
131         return XSD::QName.new(ns, name)
132       end
133     end
134     XSD::QName.new(local ? nil : @default_namespace, str)
135   end
136
137   # For local attribute key parsing
138   #   <foo xmlns="urn:a" xmlns:n1="urn:a" bar="1" n1:baz="2" />
139   #     =>
140   #   {}bar, {urn:a}baz
141   def parse_local(elem)
142     ParseRegexp =~ elem
143     if $2
144       ns = @tag2ns[$1]
145       name = $2
146       if !ns
147         raise FormatError.new("unknown namespace qualifier: #{$1}")
148       end
149     elsif $1
150       ns = nil
151       name = $1
152     else
153       raise FormatError.new("illegal element format: #{elem}")
154     end
155     XSD::QName.new(ns, name)
156   end
157
158   def each_ns
159     @ns2tag.each do |ns, tag|
160       yield(ns, tag)
161     end
162   end
163
164 protected
165
166   def assigner=(assigner)
167     @assigner = assigner
168   end
169
170 private
171
172   def ns_default
173     {'xml' => Namespace}
174   end
175
176   def default_known_tag
177     KNOWN_TAG
178   end
179 end
180
181
182 end
Note: See TracBrowser for help on using the browser.