user2652353
user2652353

Reputation: 41

How to remove the namespace from few XML nodes

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

Answers (2)

Llu&#237;s
Llu&#237;s

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

Mel T.
Mel T.

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

Related Questions