使用Nokogiri构建器创建带有命名空间根元素的XML文档

我正在为需要命名空间的XML数据格式实现导出器。 我正在使用Nokogiri XML Builder(版本1.4.0)来执行此操作。

但是,我不能让Nokogiri创建一个带有命名空间的根节点。

这有效:

Nokogiri::XML::Builder.new { |xml| xml.root('xmlns:foobar' => 'my-ns-url') }.to_xml   

就像这样:

 Nokogiri::XML::Builder.new do |xml| xml.root('xmlns:foobar' => 'my-ns-url') { xml['foobar'].child } end.to_xml     

但是,我需要像这样的东西,这不起作用:

 Nokogiri::XML::Builder.new { |xml| xml['foobar'].root('xmlns:foobar' => 'my-ns-url') }.to_xml NoMethodError: undefined method `namespace_definitions' for # 

显然,在使用之前必须定义命名空间,因此无法将其添加到根节点。

我在Nokogiri邮件列表上发现了一个关于此的问题 ,但没有回复。 有人有解决方案吗?

 require 'rubygems' require 'nokogiri' puts Nokogiri::XML::Builder.new { |xml| xml.root("xmlns:foo"=>"url") { xml.parent.namespace = xml.parent.namespace_definitions.find{|ns|ns.prefix=="foo"} xml['foo'].child } }.to_xml 

在定义命名空间之前,即在将其作为参数传递给根节点之前,不能使用xml['foo'] 。 因此,上面的代码将事后名称空间添加到根节点。

两年后,我发现了一种更Nokogiri::XML::Builder方法,通过使用Nokogiri::XML::Builder的文档引用来检索根节点并将命名空间添加到该节点。 与之前的解决方案一样,它需要在将名称空间添加到根节点之前存在根节点。

我已将元素更改为因此更清楚:

 builder = Nokogiri::XML::Builder.new do |xml| xml.rootElement do # create a namespace and save it for later ns = xml.doc.root.add_namespace_definition('foo', 'my-ns-url') # you can also create multiple name spaces xml.doc.root.add_namespace_definition('bar', 'http://example.com/bar') # assign the saved namespace to rootElement xml.doc.root.namespace = ns xml['foo'].child xml['bar'].child end end 

现在, builder.to_xml将返回:

      

我更喜欢这个,因为你不必搜索名称空间,并且更容易添加多个名称空间。

在卢克回答三年之后,它变得更加简单了。 您现在可以使用命名空间“之前”定义它。 这段代码:

 require 'nokogiri' NAMESPACES = { 'xmlns:foo' => 'bar', 'xmlns:baz' => 'bat' } builder = Nokogiri::XML::Builder.new { |xml| xml['foo'].RootElement(NAMESPACES) { xml['baz'].FirstChild } } puts builder.to_xml 

输出此XML: