本文介绍了使用 Nokogiri 的 XML Builder 添加命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几个小时以来,我一直在绞尽脑汁,但我似乎无法确定如何在使用 Nokogiri XML Builder 类构建 XML 结构的同时添加 XMLNS 命名空间.

I have been wrecking my head for a few hours but I can't seem to determine how to add XMLNS namespace whilst using the Nokogiri XML Builder class to construct a XML structure.

例如,考虑下面的 XML 示例:我可以在 GetQuote 标记之间创建所有内容,但创建p:ACMRequest"仍然是个谜.

For instance, consider the XML sample below: I can create everything between the GetQuote tags but creating the "p:ACMRequest" remains a mystery.

我看到了这个参考资料,https://gist.github.com/428455/7a189fc84b4a7ac08c54ac5ac5ac05ac05b73fcec2af49947>,这对我来说仍然没有意义.即使参考 XML 文档,http://www.w3.org/TR/xml-names/,也没有多大意义.

I came across this reference, https://gist.github.com/428455/7a15f84cc08c05b73fcec2af49947d458ae3b96a, that still doesn't make sense to me. Even referring to the XML documentation,http://www.w3.org/TR/xml-names/, didn't make much sense either.

<?xml version="1.0" encoding="UTF-8"?>
<p:ACMRequest xmlns:p="http://www.acme.com" xmlns:p1="http://www.acme.com/datatypes" xmlns:p2="http://www.acme.com/ACMRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.acme.com ACM-req.xsd ">
  <GetQuote>
    <Request>
      <ServiceHeader>
        ...
        ...
      </ServiceHeader>
    </Request>
    <From>
      ...
      ...
    </From>
    <Details>
      ...
      ...
    </Details>
  </GetQuote>
</p:ACMRequest>

推荐答案

Nokogiri 文档页面 说:

命名空间的添加类似于属性.Nokogiri::XML::Builder 假设当一个属性以xmlns"开头时,它意味着是一个命名空间:

   builder = Nokogiri::XML::Builder.new { |xml|
     xml.root('xmlns' => 'default', 'xmlns:foo' => 'bar') do
       xml.tenderlove
     end
   }
   puts builder.to_xml

会像这样输出 XML:

Will output XML like this:

   <?xml version="1.0"?>
   <root xmlns:foo="bar" xmlns="default">
     <tenderlove/>
   </root>

将此应用于您的具体问题,只需执行以下操作:

Applying this to your specific question, simply do:

require 'nokogiri'
NS = {
  "xmlns:p"   => "http://www.acme.com",
  "xmlns:p1"  => "http://www.acme.com/datatypes",
  "xmlns:p2"  => "http://www.acme.com/ACMRequestdatatypes",
  "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
}
builder = Nokogiri::XML::Builder.new { |xml|
  xml.ACMRequest(NS) do
    xml.GetQuote
  end
}
puts builder.to_xml

#=> <?xml version="1.0"?>
#=> <ACMRequest xmlns:p="http://www.acme.com" xmlns:p1="http://www.acme.com/datatypes" xmlns:p2="http://www.acme.com/ACMRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
#=>   <GetQuote/>
#=> </ACMRequest>

至于根元素本身的命名空间前缀...

As for the namespace prefix on the root element itself…

<p:ACMRequest xmlns:p="…">…</p:ACMRequest>

...我不知道如何在创建过程中将命名空间前缀应用于 Nokogiri 中的第一个元素.相反,您必须在创建文档后应用命名空间:

…I cannot figure out how to apply a namespace prefix to the first element in Nokogiri during creation. Instead, you have to apply the namespace after creating the document:

root = builder.doc.root
acme = root.namespace_definitions.find{ |ns| ns.href==NS["xmlns:p"] }
root.namespace = acme
puts builder.to_xml

#=> <?xml version="1.0"?>
#=> <p:ACMRequest xmlns:p="http://www.acme.com" xmlns:p1="http://www.acme.com/datatypes" xmlns:p2="http://www.acme.com/ACMRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">atypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
#=>   <GetQuote/>
#=> </p:ACMRequest>

或者,你可以作弊:

# This happens to work for now, but I doubt you should rely upon it.
builder.doc.root.name = "p:ACMRequest"

根据如何创建带有 Nokogiri Builder 的命名空间根元素的 XML 文档",您也可以在创建过程中通过一个小技巧来做到这一点:

Per "How to create an XML document with a namespaced root element with Nokogiri Builder" you can alternatively do this during creation via a small hack:

builder = Nokogiri::XML::Builder.new { |xml|
  xml.ACMRequest(NS) do
   xml.parent.namespace = … # find the ns in xml.parent.namespace_definitions
   # …
  end
end

这篇关于使用 Nokogiri 的 XML Builder 添加命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 20:34