13

名前空間を必要とするXMLデータのエクスポーターを実装しています。これを行うためにNokogiriのXMLBuilder(バージョン1.4.0)を使用していますが、Nokogiriに名前空間を持つルートノードを作成させることができません。

これは機能します:

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

<?xml version="1.0"?>
<root xmlns:foobar="my-ns-url"/>

これがそうであるように:

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

<?xml version="1.0"?>
<root xmlns:foobar="my-ns-url">
  <foobar:child/>
</root>

ただし、次のようなものが必要ですが<foo:root>、これは機能しません。

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

NoMethodError: undefined method `namespace_definitions' for #<Nokogiri::XML::Document:0x11bfef8 name="document">

明らかに、名前空間は使用する前に定義する必要があるため、ルートノードに名前空間を追加する方法はありません。

Nokogiriメーリングリストで「名前空間でルートノードを定義しますか? 」を見つけましたが、応答がありませんでした。

誰かが解決策を持っていますか?

4

3 に答える 3

16
require 'rubygems'
require 'nokogiri'

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

xml['foo']名前空間が定義される前、つまりルートノードに引数として渡す前にIEを使用することはできません。したがって、上記のコードは、名前空間を事後にルートノードに追加しました。

于 2009-12-06T19:14:04.777 に答える
8

2年後、Nokogiri::XML::Builderのドキュメント参照を使用してルートノードを取得し、それに名前空間を追加することで、これを行うためのよりクリーンな方法を見つけました。前のソリューションと同様に、名前空間を追加する前にルートノードが存在する必要があります。

<root>要素をに変更した<rootElement>ので、これはより明確になります。

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戻ります:

<?xml version="1.0"?>
<foo:rootElement xmlns:foo="my-ns-url" xmlns:bar="http://example.com/bar">
  <foo:child/>
  <bar:child/>
</foo:rootElement>

名前空間を検索する必要がなく、複数の名前空間を追加する方が簡単なので、これが気に入っています。

于 2012-03-28T01:02:45.383 に答える
3

ルークの答えから3年後、それはさらに単純になりました。これで、定義された「前」の名前空間を使用できます。このコード:

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を出力します:

<?xml version="1.0"?>
<foo:RootElement xmlns:foo="bar" xmlns:baz="bat">
  <baz:FirstChild/>
</foo:RootElement>
于 2015-12-01T17:02:41.400 に答える