【问题标题】:Adding a XML Element to a Nokogiri::XML::Builder document向 Nokogiri::XML::Builder 文档添加 XML 元素
【发布时间】:2015-04-03 00:20:28
【问题描述】:

如何将Nokogiri::XML::Element 添加到使用Nokogiri::XML::Buider 创建的XML 文档中?

我目前的解决方案是序列化元素并使用<< 方法让生成器重新解释它。

orig_doc = Nokogiri::XML('<root xmlns="foobar"><a>test</a></root>')
node = orig_doc.at('/*/*[1]')

puts Nokogiri::XML::Builder.new do |doc|
    doc.another {
        # FIXME: this is the round-trip I would like to avoid
        xml_text = node.to_xml(:skip_instruct => true).to_s
        doc << xml_text

        doc.second("hi")
    }
end.to_xml

# The expected result is
#
# <another>
#    <a xmlns="foobar">test</a>
#    <second>hi</second>
# </another>

但是Nokogiri::XML::Element 是一个相当大的节点(以千字节和数千个节点的顺序),并且此代码处于热路径中。分析表明,序列化/解析往返非常昂贵。

如何指示 Nokogiri Builder 在“当前”位置添加现有 XML 元素 node

【问题讨论】:

    标签: ruby xml nokogiri


    【解决方案1】:

    不使用私有方法,您可以使用the parent method of the Builder 实例获取当前父元素的句柄。然后您可以将一个元素附加到该元素(甚至来自另一个文档)。例如:

    require 'nokogiri'
    doc1 = Nokogiri.XML('<r><a>success!</a></r>')
    a = doc1.at('a')
    
    # note that `xml` is not a Nokogiri::XML::Document,
    #  but rather a Nokogiri::XML::Builder instance.
    doc2 = Nokogiri::XML::Builder.new do |xml|
      xml.some do
        xml.more do
          xml.parent << a
        end
      end
    end.doc
    
    puts doc2
    #=> <?xml version="1.0"?>
    #=> <some>
    #=>   <more>
    #=>     <a>success!</a>
    #=>   </more>
    #=> </some>
    

    【讨论】:

    • 这比我和#insert 的混搭要好得多。
    • 当我尝试这个时,我丢失了一个 xml 属性的命名空间
    【解决方案2】:

    查看 Nokogiri 源代码后,我发现了这个脆弱的解决方案:使用受保护的 #insert(node) 方法。

    修改为使用该私有方法的代码如下所示:

    doc.another {
        xml_text = node.to_xml(:skip_instruct => true).to_s
        doc.send('insert', xml_text) # <= use `#insert` instead of `<<`
    
        doc.second("hi")
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      相关资源
      最近更新 更多