1

I need to add an element to an existing XML document which uses a namespace that doesn't exist in the original. How do I do this?

Ideally I would like to use REXML for portability, but any common XML library would be okay. An ideal solution would be smart about namespace collisions.

I have an xml document which looks like this:

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

and add:

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

Yielding something equivalent to:

<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 Answer 1

1

It turns out this is a dumb question. If both the initial document and the element to be added are internally consistent, then namespaces are okay. So this is equivalent to the final document:

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

It is important that both the initial document and the element define a default namespace with the xmlns attribute.

Assume the initial document is in initial.xml, and the element is in element.xml. To create this final document with REXML, simply:

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.