【问题标题】:How do I not inherit namespace from parent element using Nokogiri and Builder?如何不使用 Nokogiri 和 Builder 从父元素继承命名空间?
【发布时间】:2014-02-17 03:05:34
【问题描述】:

首先 - 看看这段代码的火车残骸:

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

这样创建 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>

没有我所有的 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>

我有这个带有安全元素的标头部分,需要使用命名空间的格式,但是一旦我们点击请求部分(以及任何后续部分,或任何其他使用此特定 API 执行不同操作的 NodeSet...)文档要求使用非命名空间元素。

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

我用的是普通的:

builder = Nokogiri::XML::Builder.new do |xml|

而我真正感兴趣的是如何使用“builder”并执行以下操作:

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

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

请帮忙!

【问题讨论】:

    标签: ruby xml ruby-on-rails-3 xmlhttprequest nokogiri


    【解决方案1】:

    您可以通过使用其他构建器来完成此操作。

    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
    

    将导致:

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

    使用&lt;&lt; 运算符将原始字符串附加到文档中。还要注意#doc.root的使用,如果你只使用#to_xml,你会在字符串的开头得到&lt;?xml version="1.0"?&gt;

    但是,如果希望将 Request 命名为命名空间而不是子节点,则此方法并不理想,因为您必须为每个子节点使用构建器(构建器只能有 1 个根。) “roots”是使用 DocumentFragment。

    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
    

    将导致:

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

    【讨论】:

      猜你喜欢
      • 2010-12-22
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多