2009-12-01 2 views
11

네임 스페이스가 필요한 XML 데이터 형식의 내보내기를 구현 중입니다. 나는 이것을하기 위해 Nokogiri XML Builder (버전 1.4.0)를 사용하고있다.Nokogiri 빌더를 사용하여 네임 스페이스가있는 루트 요소로 XML 문서 작성

그러나 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"> 

네임 스페이스가 있어야합니다 분명히 사용하기 전에 정의되었으므로 루트 노드에 추가 할 방법이 없습니다.

a question about this on the Nokogiri mailing list을 찾았지만 답장이 없습니다. 누구나 해결책이 있습니까? 네임 스페이스가 정의되기 전에

답변

13
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']을 사용할 수 없습니다. 따라서 위의 코드는 네임 스페이스를 사실에 추가하여 루트 노드에 추가합니다.

+0

작품. 감사! –

+0

당신, 선생님, 많은 좌절을 덜어 줬습니다. – yalestar

+0

안녕, yalestar. – akuhn

6

2 년 후, Nokogiri::XML::Builder의 문서 참조를 사용하여 루트 노드를 검색하고 그에 대한 네임 스페이스를 추가하는 방법으로 더 깨끗한 방법을 발견했습니다. 이전 솔루션과 마찬가지로 네임 스페이스를 추가하기 전에 루트 노드가 존재해야합니다.

내가 <rootElement><root> 요소를 변경 한

지금이 더 분명하다 : 이제

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> 

나는이 더 좋아 네임 스페이스를 검색하면 여러 개의 네임 스페이스를 추가하는 것이 더 쉽습니다.

+0

위대한 작품. 감사. 그러나 네임 스페이스 상속을 제거 할 수 없습니다. 나는 다음과 같은 것을 성취하고 싶다. dknight

0

루크의 답변을받은 지 3 년이 지난 지금, 그것은 훨씬 간단 해졌습니다. 정의 된 "before"네임 스페이스를 사용할 수 있습니다. 이 코드 :

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>