Skip to content

Instantly share code, notes, and snippets.

@gangelo
Forked from mudge/gist:428455
Last active February 15, 2019 14:45
Show Gist options
  • Save gangelo/032dcf53597b3d16f56d10166acc8849 to your computer and use it in GitHub Desktop.
Save gangelo/032dcf53597b3d16f56d10166acc8849 to your computer and use it in GitHub Desktop.
Namespaces with Nokogiri::Builder
# Dealing with namespaces in Nokogiri.
#
# First thing you must do is abandon what you're used to with Builder,
# namespaces aren't just attributes on an element, they uniquely identify
# what sort of element you are building and, as such, you are better off
# specifying them manually.
#
# The key here is accessing the Nokogiri::XML::Element being built with
# b.parent, then you can set the namespace (distinguished by an element
# with a prefix such as "soap12:Envelope") or add a default namespace
# (where there is no prefix but an "xmlns" attribute).
#
# The example below shows both types of namespaces being created and used
# including setting a namespace on the root element of a document.
#
# Thanks to http://stackoverflow.com/questions/1829425/creating-an-xml-document-with-a-namespaced-root-element-with-nokogiri-builder
# for pointing me in the right direction.
b = Nokogiri::XML::Builder.new
b.Envelope("xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema") {
b.parent.namespace = b.parent.add_namespace_definition("soap12", "http://www.w3.org/2003/05/soap-envelope")
b['soap12'].Body {
b.Foo {
b.parent.default_namespace = "http://FOO/Bar"
b.exampleXML {
b.example("xsi:schemaLocation" => "http://www.example.com/schemas https://service.example.com/FOO/schemas/monkey.xsd") {
b.parent.add_namespace_definition("xsi", "http://www.w3.org/2001/XMLSchema-instance")
b.parent.default_namespace = "http://www.example.com/schemas"
b.dummy("Test")
b.domain("woo")
b.person {
b.name("test")
}
}
}
}
}
}
# This will create the following XML:
#
# <?xml version="1.0"?>
# <soap12:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
# <soap12:Body>
# <Foo xmlns="http://FOO/Bar">
# <exampleXML>
# <example xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.example.com/schemas" xsi:schemaLocation="http://www.example.com/schemas https://service.example.com/FOO/schemas/monkey.xsd">
# <dummy>Test</dummy>
# <domain>woo</domain>
# <person>
# <name>test</name>
# </person>
# </example>
# </exampleXML>
# </Foo>
# </soap12:Body>
# </soap12:Envelope>
#
# Now that it's all namespaced properly, don't forget how to select
# elements with XPath: http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/
#
# n = Nokogiri::XML(b.to_xml)
# n.xpath("//n:Foo", "xmlns:n" => "http://FOO/Bar")
# n.xpath("//n:dummy", "xmlns:n" => "http://www.example.com/schemas")
# n.xpath("//n:person/n:name", "xmlns:n" => "http://www.example.com/schemas")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment