Domanda

Sono l'attuazione di un esportatore di un formato di dati XML che richiede spazi dei nomi. Sto utilizzando la Nokogiri XML Builder (versione 1.4.0) per fare questo.

Tuttavia, non riesco a Nokogiri per creare un nodo principale con uno spazio dei nomi.

Questo funziona:

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

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

Come fa questo:

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>

Tuttavia, ho bisogno di qualcosa come <foo:root> e questo non funziona:

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">

Gli spazi dei nomi devono essere definiti prima dell'uso, a quanto pare, quindi non c'è modo di aggiungere uno al nodo radice.

un'informazione riguardo questo sul Nokogiri mailing list , ma non aveva risposte. Qualcuno ha una soluzione?

È stato utile?

Soluzione

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

Non è possibile utilizzare xml['foo'] prima che lo spazio dei nomi è definito, vale a dire prima di passare come argomento al nodo radice. Così, il codice sopra aggiungere il namespace dopo-il-fatto al nodo radice.

Altri suggerimenti

Due anni più tardi, ho trovato un modo più pulito per fare questo usando riferimento del documento di Nokogiri::XML::Builder per recuperare il nodo principale e aggiungere il namespace (s) a questo. Come soluzione precedente, richiede il nodo radice esistere prima namespace possono essere aggiunti ad esso.

Ho cambiato l'elemento <root> a <rootElement> quindi questo è più chiaro:

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

Ora, builder.to_xml tornerà:

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

Mi piace questo meglio, perché non c'è bisogno di cercare il nome di spazio, ed è più facile per aggiungere più spazi dei nomi.

Tre anni dopo la risposta di Luca, si è ottenuto ancora più semplice. È ora possibile utilizzare lo spazio dei nomi "prima" è definito. Questo codice:

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

Risulterà XML:

<?xml version="1.0"?>
<foo:RootElement xmlns:foo="bar" xmlns:baz="bat">
  <baz:FirstChild/>
</foo:RootElement>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top