Добавить пространство имен XML в существующий документ в ruby - PullRequest
1 голос
/ 08 марта 2009

Мне нужно добавить элемент в существующий XML-документ, который использует пространство имен, которого нет в оригинале. Как мне это сделать?

В идеале я хотел бы использовать REXML для переносимости, но любая обычная библиотека XML будет в порядке. Идеальное решение было бы разумно для коллизий пространства имен.

У меня есть документ XML, который выглядит следующим образом:

<xrds:XRDS
 xmlns:xrds="xri://$xrds"
 xmlns="xri://$xrd*($v*2.0)">
    <XRD>
        <Service>
            <Type>http://specs.openid.net/auth/2.0/signon</Type>
            <URI>http://provider.openid.example/server/2.0</URI>
        </Service>
    </XRD>
</xrds:XRDS>

и добавьте:

<Service
 xmlns="xri://$xrd*($v*2.0)"
 xmlns:openid="http://openid.net/xmlns/1.0">
    <Type>http://openid.net/signon/1.0</Type>
    <URI>http://provider.openid.example/server/1.0</URI>
    <openid:Delegate>http://example.openid.example</openid:Delegate>
</Service>

Дает что-то эквивалентное:

<xrds:XRDS
 xmlns:xrds="xri://$xrds"
 xmlns="xri://$xrd*($v*2.0)"
 xmlns:openid="http://openid.net/xmlns/1.0">
    <XRD>
        <Service>
            <Type>http://specs.openid.net/auth/2.0/signon</Type>
            <URI>http://provider.openid.example/server/2.0</URI>
        </Service>
        <Service>
            <Type>http://openid.net/signon/1.0</Type>
            <URI>http://provider.openid.example/server/1.0</URI>
            <openid:Delegate>http://example.openid.example</openid:Delegate>
        </Service>
    </XRD>
</xrds:XRDS>

1 Ответ

1 голос
/ 08 марта 2009

Оказывается, это глупый вопрос. Если и исходный документ, и добавляемый элемент внутренне согласованы, то пространства имен в порядке. Так что это эквивалентно итоговому документу:

<xrds:XRDS
 xmlns:xrds="xri://$xrds"
 xmlns="xri://$xrd*($v*2.0)">
    <XRD>
        <Service>
            <Type>http://specs.openid.net/auth/2.0/signon</Type>
            <URI>http://provider.openid.example/server/2.0</URI>
        </Service>
        <Service
         xmlns:openid="http://openid.net/xmlns/1.0" 
         xmlns="xri://$xrd*($v*2.0)">
            <Type>http://openid.net/signon/1.0</Type>
            <URI>http://provider.openid.example/server/1.0</URI>
            <openid:Delegate>http://example.openid.example</openid:Delegate>
        </Service>
    </XRD>
</xrds:XRDS>

Важно, чтобы и исходный документ, и элемент определяли пространство имен по умолчанию с атрибутом xmlns.

Предположим, что исходный документ находится в initial.xml, а элемент в element.xml. Чтобы создать этот окончательный документ с помощью REXML, просто:

require 'rexml/document'
include REXML

document = Document.new(File.new('initial.xml'))
unless document.root.attributes['xmlns']
  raise "No default namespace in initial document" 
end
element = Document.new(File.new('element.xml'))
unless element.root.attributes['xmlns']
  raise "No default namespace in element" 
end

xrd = document.root.elements['XRD']
xrd.elements << element
document
...