Reputation: 41
I need to read an XML file and generate a SOAP request body using Nokogiri in Ruby on Rails.
The request body that I need to generate is:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:c2="http://c2_0.customer.webservices.csx.dtv.com/">
<soapenv:Header>
<soapenv:Body>
<c2:getCustomer>
<customerId>10</customerId>
<UserId>adminUser</UserId>
</c2:getCustomer>
</soapenv:Body>
</soapenv:Header>
</soapenv:Envelope>
I am using this code:
require 'nokogiri'
doc = Nokogiri::XML(File.open('p_l_s.xml'))
wsID =doc.xpath('//transaction:WsID' , 'transaction' => 'http://www.nrf-arts.org/IXRetail/namespace/').inner_text
builder = Nokogiri::XML::Builder.new do |xml|
xml.Envelope("xmlns:soapenv" => "http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:c2" => "http://c2_0.customer.webservices.csx.dtv.com/") do
xml.parent.namespace = xml.parent.namespace_definitions.first
xml['soapenv'].Header {
xml.Body {
xml['c2'].getCustomer{
#xml.remove_namespaces!
xml.customerId wsID
xml.UserId "adminUser"
}
}
}
end
end
puts builder.to_xml
And, when executing it from the terminal in Ubuntu, I get:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:c2="http://c2_0.customer.webservices.csx.dtv.com/">
<soapenv:Header>
<soapenv:Body>
<c2:getCustomer>
<c2:customerId>10</c2:customerId>
<c2:UserId>adminUser</c2:UserId>
</c2:getCustomer>
</soapenv:Body>
</soapenv:Header>
</soapenv:Envelope>
I get the c2
namespace for the XML elements customerId
and UserId
which is not required for the method I'm invoking in the WSDL file I will be calling.
Upvotes: 3
Views: 2247
Reputation: 1317
I think this code in Mel T's answer:
xml.customerId {
xml.parent.content=(wsID)
xml.parent.namespace = xml.parent.namespace_definitions.first
}
Would output:
<soapenv:customerId>10</soapenv:customerId>
I did this instead:
xml.customerId {
xml.parent.content=(wsID)
xml.parent.namespace = nil
}
Upvotes: 2
Reputation: 116
I was able to generate the output you needed with the following code:
builder = Nokogiri::XML::Builder.new do |xml|
xml.Envelope("xmlns:soapenv" => "http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:c2" => "http://c2_0.customer.webservices.csx.dtv.com/") do
xml.parent.namespace = xml.parent.namespace_definitions.first
xml.Header {
xml.Body {
xml.getCustomer {
xml.customerId {
xml.parent.content=(wsID)
xml.parent.namespace = xml.parent.namespace_definitions.first
}
xml.UserId{
xml.parent.content=("adminUser")
xml.parent.namespace = xml.parent.namespace_definitions.first
}
xml.parent.namespace = xml.parent.namespace_scopes[1]
}
}
}
end
end
puts builder.to_xml
You don't have to explicitly set namespaces until you get to 'getCustomer'. With a combination of the 'content' and 'namespace_definition' methods, you can then specify the namespace and content of the child nodes - which should output what you were looking for.
The Nogokiri pages for the Builder: http://nokogiri.org/Nokogiri/HTML/Builder.html and Node: http://nokogiri.org/Nokogiri/XML/Node.html are super useful and will hopefully help shed more light on this for you.
Upvotes: 2