如何从少数XML节点中删除命名空间

时间:2013-08-05 09:06:58

标签: ruby-on-rails ruby xml nokogiri xml-namespaces

我需要在Ruby on Rails中使用Nokogiri读取XML文件并生成SOAP请求体。

我需要生成的请求正文是:

<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>

我正在使用此代码:

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

而且,当从Ubuntu的终端执行它时,我得到:

<?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>

我获得了XML元素c2customerId的{​​{1}}命名空间,这是我将要调用的WSDL文件中调用的方法所不需要的。

2 个答案:

答案 0 :(得分:1)

我能够使用以下代码生成您需要的输出:

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

在进入'getCustomer'之前,您不必显式设置名称空间。通过'content'和'namespace_definition'方法的组合,您可以指定子节点的名称空间和内容 - 它们应该输出您要查找的内容。

构建器的Nogokiri页面:http://nokogiri.org/Nokogiri/HTML/Builder.html和节点:http://nokogiri.org/Nokogiri/XML/Node.html非常有用,希望能帮助您更好地了解这一点。

答案 1 :(得分:1)

我认为这段代码在Mel T的回答中:

xml.customerId {
  xml.parent.content=(wsID)
  xml.parent.namespace = xml.parent.namespace_definitions.first
}

输出:

<soapenv:customerId>10</soapenv:customerId>

我这样做了:

xml.customerId {
  xml.parent.content=(wsID)
  xml.parent.namespace = nil
}