Adding a namespace using Nokogiri XML Builder

I've been racking my brains for hours, but I can't figure out how to add the XMLNS namespace using the Nokogiri XML Builder class to build the XML structure.

For example, consider the XML sample below: I can create everything between GetQuote tags, but creating "p: ACMRequest" remains a mystery.

I came across this link, https://gist.github.com/428455/7a15f84cc08c05b73fcec2af49947d458ae3b96a , which still doesn't make sense to me. Even referring to the XML documentation, http://www.w3.org/TR/xml-names/ also doesn't make much sense.

<?xml version="1.0" encoding="UTF-8"?> <p:ACMRequest xmlns:p="http://www.acme.com" xmlns:p1="http://www.acme.com/datatypes" xmlns:p2="http://www.acme.com/ACMRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.acme.com ACM-req.xsd "> <GetQuote> <Request> <ServiceHeader> ... ... </ServiceHeader> </Request> <From> ... ... </From> <Details> ... ... </Details> </GetQuote> </p:ACMRequest> 
+4
source share
2 answers

If you are Google for "nokogiri xml builder namespace" , the first hit is the Nokogiri documentation page , which says:

Namespaces are added in the same way as attributes. Nokogiri::XML::Builder assumes that when an attribute begins with "xmlns", it must be a namespace:

  builder = Nokogiri::XML::Builder.new { |xml| xml.root('xmlns' => 'default', 'xmlns:foo' => 'bar') do xml.tenderlove end } puts builder.to_xml 

Output XML as follows:

  <?xml version="1.0"?> <root xmlns:foo="bar" xmlns="default"> <tenderlove/> </root> 

Applying this to your specific question, simply do:

 require 'nokogiri' NS = { "xmlns:p" => "http://www.acme.com", "xmlns:p1" => "http://www.acme.com/datatypes", "xmlns:p2" => "http://www.acme.com/ACMRequestdatatypes", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", } builder = Nokogiri::XML::Builder.new { |xml| xml.ACMRequest(NS) do xml.GetQuote end } puts builder.to_xml #=> <?xml version="1.0"?> #=> <ACMRequest xmlns:p="http://www.acme.com" xmlns:p1="http://www.acme.com/datatypes" xmlns:p2="http://www.acme.com/ACMRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> #=> <GetQuote/> #=> </ACMRequest> 

Regarding the namespace prefix on the root element itself ...

 <p:ACMRequest xmlns:p="…"></p:ACMRequest> 

... I cannot figure out how to apply the namespace prefix to the first element in Nokogiri at creation time. Instead, you should apply the namespace after creating the document:

 root = builder.doc.root acme = root.namespace_definitions.find{ |ns| ns.href==NS["xmlns:p"] } root.namespace = acme puts builder.to_xml #=> <?xml version="1.0"?> #=> <p:ACMRequest xmlns:p="http://www.acme.com" xmlns:p1="http://www.acme.com/datatypes" xmlns:p2="http://www.acme.com/ACMRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">atypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> #=> <GetQuote/> #=> </p:ACMRequest> 

Alternatively, you can cheat:

 # This happens to work for now, but I doubt you should rely upon it. builder.doc.root.name = "p:ACMRequest" 

Per " Creating an XML document with a root element with a namespace using Nokogiri builder " you can alternatively do this during creation with a little hack:

 builder = Nokogiri::XML::Builder.new { |xml| xml.ACMRequest(NS) do xml.parent.namespace = … # find the ns in xml.parent.namespace_definitions # … end end 
+10
source
 require 'nokogiri' NS = { "xmlns:p" => "http://www.acme.com", "xmlns:p1" => "http://www.acme.com/datatypes", "xmlns:p2" => "http://www.acme.com/ACMRequestdatatypes", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", } builder = Nokogiri::XML::Builder.new { |xml| xml['p'].ACMRequest(NS) do xml.GetQuote end } puts builder.to_xml 

It produces:

 <?xml version="1.0"?> <p:ACMRequest xmlns:p="http://www.acme.com" xmlns:p1="http://www.acme.com/datatypes" xmlns:p2="http://www.acme.com/ACMRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <p:GetQuote/> </p:ACMRequest> 

This is described in the builder API: http://nokogiri.org/Nokogiri/XML/Builder.html :

Link to declared namespaces

Tags that reference namespaces other than the default values ​​(that is, the foo: bar tag) can be constructed using the Nokogiri :: XML :: Builder # [] method.

+9
source

Source: https://habr.com/ru/post/1379646/


All Articles