我一直在破坏我的头几个小时,但我似乎无法确定如何在使用Nokogiri XML Builder类构建XML结构时添加XMLNS名称空间。
例如,考虑下面的XML示例:我可以在GetQuote标记之间创建所有内容,但创建“p:ACMRequest”仍然是一个谜。
我遇到了这个引用https://gist.github.com/428455/7a15f84cc08c05b73fcec2af49947d458ae3b96a,这对我来说仍然没有意义。即使参考XML文档,http://www.w3.org/TR/xml-names/,也没有多大意义。
<?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>
答案 0 :(得分:14)
如果您使用Google "nokogiri xml builder namespace",那么首次点击是Nokogiri documentation page,其中包含:
与属性类似地添加命名空间。
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:
<?xml version="1.0"?> <root xmlns:foo="bar" xmlns="default"> <tenderlove/> </root>
将此问题应用于您的具体问题,只需执行以下操作:
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>
至于根元素本身的名称空间前缀......
<p:ACMRequest xmlns:p="…">…</p:ACMRequest>
...我无法弄清楚如何在创建过程中将名称空间前缀应用于Nokogiri中的第一个元素。相反,您必须在创建文档后应用命名空间:
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"
每个“Creating an XML document with a namespaced root element with Nokogiri builder”您可以通过小型黑客在创建过程中执行此操作:
builder = Nokogiri::XML::Builder.new { |xml|
xml.ACMRequest(NS) do
xml.parent.namespace = … # find the ns in xml.parent.namespace_definitions
# …
end
end
答案 1 :(得分:12)
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['p'].ACMRequest(NS) do
xml.GetQuote
end
}
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">
<p:GetQuote/>
</p:ACMRequest>
构建器API中记录了这一点:http://nokogiri.org/Nokogiri/XML/Builder.html:
引用声明的名称空间
引用非默认命名空间(即标签“foo:bar”)的标签可以 使用Nokogiri :: XML :: Builder#[]方法构建。