Reputation: 20928
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>
Upvotes: 1
Views: 1112
Reputation: 20928
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
Upvotes: 1