Skip to content

Commit

Permalink
* XML attribute must not be affected by default namespace. closes #430.
Browse files Browse the repository at this point in the history
git-svn-id: http://dev.ctor.org/svn/soap4r/trunk@1975 23c4dcf6-64ea-0310-84d7-d424c7495ec0
  • Loading branch information
nahi committed Sep 19, 2007
1 parent 17a77fd commit 22d9513
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 62 deletions.
17 changes: 14 additions & 3 deletions lib/soap/encodingstyle/handler.rb
Expand Up @@ -94,12 +94,23 @@ def decode_prologue
def decode_epilogue
end

def encode_attr_key(attrs, ns, qname)
if qname.namespace.nil?
qname.name
else
unless ns.assigned_as_tagged?(qname.namespace)
Generator.assign_ns!(attrs, ns, qname.namespace)
end
ns.name_attr(qname)
end
end

def encode_qname(attrs, ns, qname)
unless qname.namespace.nil?
if qname.namespace.nil?
qname.name
else
Generator.assign_ns(attrs, ns, qname.namespace)
ns.name(qname)
else
qname.name
end
end
end
Expand Down
3 changes: 1 addition & 2 deletions lib/soap/encodingstyle/literalHandler.rb
Expand Up @@ -31,10 +31,9 @@ def encode_data(generator, ns, data, parent)
name = generator.encode_name(ns, data, attrs)
data.extraattr.each do |key, value|
next if !@generate_explicit_type and key == XSD::AttrTypeName
# ToDo: check generator.attributeformdefault here
keytag = key
if key.is_a?(XSD::QName)
keytag = encode_qname(attrs, ns, key)
keytag = encode_attr_key(attrs, ns, key)
end
if value.is_a?(XSD::QName)
value = encode_qname(attrs, ns, value)
Expand Down
2 changes: 1 addition & 1 deletion lib/soap/encodingstyle/soapHandler.rb
Expand Up @@ -301,7 +301,7 @@ def encode_attrs(generator, ns, data, parent)
data.extraattr.each do |key, value|
keytag = key
if key.is_a?(XSD::QName)
keytag = encode_qname(attrs, ns, key)
keytag = encode_attr_key(attrs, ns, key)
end
if value.is_a?(XSD::QName)
value = encode_qname(attrs, ns, value)
Expand Down
74 changes: 40 additions & 34 deletions lib/soap/generator.rb
Expand Up @@ -40,7 +40,6 @@ def initialize(opt = {})
@default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
@generate_explicit_type =
opt.key?(:generate_explicit_type) ? opt[:generate_explicit_type] : true
# ':elementformdefault' is for backward compatibility
@use_default_namespace = opt[:use_default_namespace]
@attributeformdefault = opt[:attributeformdefault]
@use_numeric_character_reference = opt[:use_numeric_character_reference]
Expand All @@ -53,9 +52,7 @@ def initialize(opt = {})
def generate(obj, io = nil)
@buf = io || ''
@indent = ''
@encode_char_regexp =
ENCODE_CHAR_REGEXP[XSD::Charset.encoding] ||=
Regexp.new("[#{EncodeMap.keys.join}]", nil, XSD::Charset.encoding)
@encode_char_regexp = get_encode_char_regexp()

prologue
@handlers.each do |uri, handler|
Expand Down Expand Up @@ -212,6 +209,42 @@ def encode_rawstring(str)
@buf << str
end

def encode_string(str)
@buf << get_encoded(str)
end

def element_local?(element)
element.elename.namespace.nil?
end

def self.assign_ns(attrs, ns, namespace, tag = nil)
if namespace.nil?
raise FormatEncodeError.new("empty namespace")
end
override_default_ns = (tag == '' and namespace != ns.default_namespace)
if override_default_ns or !ns.assigned?(namespace)
assign_ns!(attrs, ns, namespace, tag)
end
end

def self.assign_ns!(attrs, ns, namespace, tag = nil)
tag = ns.assign(namespace, tag)
if tag == ''
attr = 'xmlns'
else
attr = "xmlns:#{tag}"
end
attrs[attr] = namespace
end

private

def prologue
end

def epilogue
end

ENCODE_CHAR_REGEXP = {}

EncodeMap = {
Expand All @@ -223,10 +256,6 @@ def encode_rawstring(str)
"\r" => '&#xd;'
}

def encode_string(str)
@buf << get_encoded(str)
end

def get_encoded(str)
if @use_numeric_character_reference and !XSD::Charset.is_us_ascii(str)
str.gsub!(@encode_char_regexp) { |c| EncodeMap[c] }
Expand All @@ -242,32 +271,9 @@ def get_encoded(str)
end
end

def element_local?(element)
element.elename.namespace.nil?
end

def self.assign_ns(attrs, ns, namespace, tag = nil)
if namespace.nil?
raise FormatEncodeError.new("empty namespace")
end
override_default_ns = (tag == '' and namespace != ns.default_namespace)
if override_default_ns or !ns.assigned?(namespace)
tag = ns.assign(namespace, tag)
if tag == ''
attr = 'xmlns'
else
attr = "xmlns:#{tag}"
end
attrs[attr] = namespace
end
end

private

def prologue
end

def epilogue
def get_encode_char_regexp
ENCODE_CHAR_REGEXP[XSD::Charset.encoding] ||=
Regexp.new("[#{EncodeMap.keys.join}]", nil, XSD::Charset.encoding)
end

def find_handler(encodingstyle)
Expand Down
21 changes: 9 additions & 12 deletions lib/soap/rpc/proxy.rb
Expand Up @@ -131,17 +131,13 @@ def call(name, *params)
:envelopenamespace => @options["soap.envelope.requestnamespace"],
:default_encodingstyle =>
@default_encodingstyle || op_info.request_default_encodingstyle,
:use_default_namespace => @use_default_namespace,
:elementformdefault => op_info.elementformdefault,
:attributeformdefault => op_info.attributeformdefault
:use_default_namespace =>
op_info.use_default_namespace || @use_default_namespace
)
resopt = create_encoding_opt(
:envelopenamespace => @options["soap.envelope.responsenamespace"],
:default_encodingstyle =>
@default_encodingstyle || op_info.response_default_encodingstyle,
:use_default_namespace => @use_default_namespace,
:elementformdefault => op_info.elementformdefault,
:attributeformdefault => op_info.attributeformdefault
@default_encodingstyle || op_info.response_default_encodingstyle
)
env = route(req_header, req_body, reqopt, resopt)
if op_info.response_use.nil?
Expand Down Expand Up @@ -354,18 +350,19 @@ class Operation
attr_reader :response_style
attr_reader :request_use
attr_reader :response_use
attr_reader :elementformdefault
attr_reader :attributeformdefault
attr_reader :use_default_namespace

def initialize(soapaction, param_def, opt)
@soapaction = soapaction
@request_style = opt[:request_style]
@response_style = opt[:response_style]
@request_use = opt[:request_use]
@response_use = opt[:response_use]
# set nil(unqualified) by default
@elementformdefault = opt[:elementformdefault]
@attributeformdefault = opt[:attributeformdefault]
@use_default_namespace =
opt[:use_default_namespace] || opt[:elementformdefault]
if opt.key?(:elementformdefault)
warn("option :elementformdefault is deprecated. use :use_default_namespace instead")
end
check_style(@request_style)
check_style(@response_style)
check_use(@request_use)
Expand Down
4 changes: 1 addition & 3 deletions lib/soap/wsdlDriver.rb
Expand Up @@ -127,9 +127,7 @@ def add_operation(drv, port)
:request_style => op_bind.soapoperation_style,
:response_style => op_bind.soapoperation_style,
:request_use => op_bind.soapbody_use_input,
:response_use => op_bind.soapbody_use_output,
:elementformdefault => false,
:attributeformdefault => false
:response_use => op_bind.soapbody_use_output
}
if op_bind.soapoperation_style == :rpc
drv.add_rpc_operation(op_name, soapaction, name, param_def, opt)
Expand Down
27 changes: 20 additions & 7 deletions lib/xsd/ns.rb
Expand Up @@ -24,7 +24,7 @@ class Assigner
attr_reader :known_tag

def initialize(known_tag)
@known_tag = known_tag
@known_tag = known_tag.dup
@count = 0
end

Expand Down Expand Up @@ -76,6 +76,10 @@ def assigned?(ns)
@default_namespace == ns or @ns2tag.key?(ns)
end

def assigned_as_tagged?(ns)
@ns2tag.key?(ns)
end

def assigned_tag?(tag)
@tag2ns.key?(tag)
end
Expand All @@ -87,13 +91,22 @@ def clone_ns
cloned
end

def name(name)
if (name.namespace == @default_namespace)
name.name
elsif tag = @ns2tag[name.namespace]
"#{tag}:#{name.name}"
def name(qname)
if qname.namespace == @default_namespace
qname.name
elsif tag = @ns2tag[qname.namespace]
"#{tag}:#{qname.name}"
else
raise FormatError.new("namespace: #{qname.namespace} not defined yet")
end
end

# no default namespace
def name_attr(qname)
if tag = @ns2tag[qname.namespace]
"#{tag}:#{qname.name}"
else
raise FormatError.new("namespace: #{name.namespace} not defined yet")
raise FormatError.new("namespace: #{qname.namespace} not defined yet")
end
end

Expand Down
35 changes: 35 additions & 0 deletions test/soap/test_custom_ns.rb
Expand Up @@ -36,6 +36,24 @@ class TestCustomNs < Test::Unit::TestCase
bar:baz="qux">bi</myns:test>
</ENV:Body>
</ENV:Envelope>
__XML__

XML_WITH_DEFAULT_NS = <<__XML__.chomp
<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header>
<headeritem xmlns="my:foo">hi</headeritem>
</env:Header>
<env:Body>
<test xmlns:n1="my:bar"
xmlns:n2="my:foo"
n1:baz="qux"
n2:quxx="quxxx"
xmlns="my:foo">bi</test>
</env:Body>
</env:Envelope>
__XML__

def test_custom_ns
Expand Down Expand Up @@ -64,6 +82,23 @@ def test_custom_ns
result = SOAP::Processor.marshal(env, opt)
assert_equal(CUSTOM_NS_XML, result)
end

def test_default_namespace
# create test env
header = SOAP::SOAPHeader.new()
hi = SOAP::SOAPElement.new(XSD::QName.new("my:foo", "headeritem"), 'hi')
header.add("test", hi)
body = SOAP::SOAPBody.new()
bi = SOAP::SOAPElement.new(XSD::QName.new("my:foo", "bodyitem"), 'bi')
bi.extraattr[XSD::QName.new('my:bar', 'baz')] = 'qux'
bi.extraattr[XSD::QName.new('my:foo', 'quxx')] = 'quxxx'
body.add("test", bi)
env = SOAP::SOAPEnvelope.new(header, body)
# normal
opt = {:use_default_namespace => true}
result = SOAP::Processor.marshal(env, opt)
assert_equal(XML_WITH_DEFAULT_NS, result)
end
end


Expand Down

0 comments on commit 22d9513

Please sign in to comment.