如何不使用Nokogiri和Builder从父元素继承名称空间?

not*_*ceo 5 ruby xml xmlhttprequest nokogiri ruby-on-rails-3

首先-查看此火车残骸代码:

xml['soapenv'].Body {
          xml.Request {
            xml.version                   ("1.1") {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.name          (@admin_name.name) {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.source_version       ("1.0") {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.downloadmarked          ("0") {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.from  (@dateFrom) {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.time_from  ("0000") {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.to    (@dateTo) {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.time_to    ("2359") {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.limit             ("100") {
              xml.parent.namespace = xml.parent.namespace_definitions.first
            }
            xml.parent.namespace = xml.parent.namespace_definitions.first
          }
        }
Run Code Online (Sandbox Code Playgroud)

这将创建如下XML:

  <soapenv:Body>
    <Request>
      <version>1.1</version>
      <name>COMPANY NAME HERE</name>
      <source_version>1.0</source_version>
      <downloadmarked>0</downloadmarked>
      <from>20140125</from>
      <time_from>0000</time_from>
      <to>20140125</to>
      <time_to>2359</time_to>
      <limit>100</limit>
    </Request>
  </soapenv:Body>
Run Code Online (Sandbox Code Playgroud)

如果没有我所有的namespace_definitions黑客,那么XML就会像这样出现:

  <soapenv:Body>
    <soapenv:Request>
      <soapenv:version>1.1</soapenv:version>
      <soapenv:name>COMPANY NAME HERE</soapenv:name>
      <soapenv:source_version>1.0</soapenv:source_version>
      <soapenv:downloadmarked>0</soapenv:downloadmarked>
      <soapenv:from>20140125</soapenv:from>
      <soapenv:time_from>0000</soapenv:time_from>
      <soapenv:to>20140125</soapenv:to>
      <soapenv:time_to>2359</soapenv:time_to>
      <soapenv:limit>100</soapenv:limit>
    </soapenv:Request>
  </soapenv:Body>
Run Code Online (Sandbox Code Playgroud)

我已经获得了带有安全元素的标头部分,这些安全元素需要使用名称空间的格式,但是一旦我们点击了Request部分(以及任何后续部分,或者使用此特定API执行其他操作的任何其他NodeSet ...),文档调用用于非命名元素。

一个简单的问题是:如何生成嵌套在具有命名空间定义的父元素内的NodeSet,而又不继承父元素的命名空间(没有我一起做过的令人作呕的hack)?

我正在使用常见的:

builder = Nokogiri::XML::Builder.new do |xml|
Run Code Online (Sandbox Code Playgroud)

我真正感兴趣的是如何接受“构建者”并做类似的事情:

    el = builder.at_xpath('//Body')
    newEl = Nokogiri::XML::Node.new do |node|
    ...my node stuff here...
    end
el.add_child(newEl)
Run Code Online (Sandbox Code Playgroud)

这样我就可以将此标头部分(所有消息都需要)抽象为它自己的方法,并在不同的主体部分上进行缝合以实现通过API公开的功能。

请帮忙!

小智 3

您可以通过使用额外的构建器来实现这一点。

xml['soapenv'].Body do
  xml << Nokogiri::XML::Builder.new do |request_xml|
    xml.Request do
      request_xml.version        "1.1"
      request_xml.name           @admin_name.name
      request_xml.source_version "1.0"
      request_xml.downloadmarked "0"
      request_xml.from           @dateFrom
      request_xml.time_from      "0000"
      request_xml.to             @dateTo
      request_xml.time_to        "2359"
      request_xml.limit          "100"
    end
  end.doc.root.to_xml
end
Run Code Online (Sandbox Code Playgroud)

将导致:

<soapenv:Body>
  <Request>
    <version>1.1</version>
    <name>COMPANY NAME HERE</name>
    <source_version>1.0</source_version>
    <downloadmarked>0</downloadmarked>
    <from>20140125</from>
    <time_from>0000</time_from>
    <to>20140125</to>
    <time_to>2359</time_to>
    <limit>100</limit>
  </Request>
</soapenv:Body>
Run Code Online (Sandbox Code Playgroud)

使用<<运算符将​​原始字符串附加到文档中。另请注意 的使用#doc.root,如果您只使用,#to_xml您将得到<?xml version="1.0"?>字符串的开头。

但是,如果Request需要命名空间而不是其子级,则这种方法并不理想,因为您必须为每个子级使用一个构建器(一个构建器只能有 1 个根。)多个“根”的解决方案是使用一个文档片段。

xml['soapenv'].Body do
  request = Nokogiri::XML::DocumentFragment.parse ""

  Nokogiri::XML::Builder.with(request) do |request_xml|
    request_xml.version        "1.1"
    request_xml.name           @admin_name.name
    request_xml.source_version "1.0"
    request_xml.downloadmarked "0"
    request_xml.from           @dateFrom
    request_xml.time_from      "0000"
    request_xml.to             @dateTo
    request_xml.time_to        "2359"
    request_xml.limit          "100"
  end

  xml.Request << request.to_xml
end
Run Code Online (Sandbox Code Playgroud)

将导致:

<soapenv:Body>
  <soapenv:Request>
    <version>1.1</version>
    <name>COMPANY NAME HERE</name>
    <source_version>1.0</source_version>
    <downloadmarked>0</downloadmarked>
    <from>20140125</from>
    <time_from>0000</time_from>
    <to>20140125</to>
    <time_to>2359</time_to>
    <limit>100</limit>
  </soapenv:Request>
</soapenv:Body>
Run Code Online (Sandbox Code Playgroud)