Print an XML document without the XML header line at the top
Asked Answered
M

2

11

I am just trying to find out how to to a to_xml with a Nokogiri::XML::Document or a Nokogiri::XML::DocumentFragment.

Alternatively, I would like to use xPath on a Nokogiri::XML::DocumentFragment. I was unable to ascertain how to do that, however I am successfully parsing a Nokogiri::XML::Document.

I am later including a parsed and modified DocumentFragment into another piece of XML, but I'm really getting bitten on what I thought would be some really simple things.

Like trying to do a to_xml on a doc or docfrag, and NOT INCLUDING that xml line at the top. Why so hard?

Marcomarconi answered 21/11, 2011 at 21:22 Comment(1)
Your 'question' is a little rambling. What does XPath on a doc fragment have to do with this question?Larrikin
L
26

The simplest way to get the XML for a Document without the leading "PI" (processing instruction) is to call to_s on the root element instead of the document itself:

require 'nokogiri'
doc = Nokogiri.XML('<hello world="true" />')

puts doc
#=> <?xml version="1.0"?>
#=> <hello world="true"/>

puts doc.root
#=> <hello world="true"/>

The 'correct' way to do it at the document or builder level, though, is to use SaveOptions:

formatted_no_decl = Nokogiri::XML::Node::SaveOptions::FORMAT +
                    Nokogiri::XML::Node::SaveOptions::NO_DECLARATION

puts doc.to_xml( save_with:formatted_no_decl )
#=> <hello world="true"/>

# Making your code shorter, but horribly confusing for future readers
puts doc.to_xml save_with:3
#=> <hello world="true"/>

 


Note that DocumentFragments do not automatically include this PI:

frag = Nokogiri::XML::DocumentFragment.parse('<hello world="true" />')
puts frag
#=> <hello world="true"/>

If you are seeing a PI in your fragment output, it means it was there when you parsed it.

xml = '<?xml version="1.0"?><hello world="true" />'
frag = Nokogiri::XML::DocumentFragment.parse(xml)
puts frag
#=> <?xml version="1.0"?><hello world="true"/>

If so, and you want to get rid of any PIs, you can do so should be able to do so with a little XPath:

frag.xpath('//processing-instruction()').remove
puts frag

…except that this does not appear to work due to oddness with XPath in DocumentFragments. To work around these bugs do this instead:

# To remove only PIs at the root level of the fragment
frag.xpath('processing-instruction()').remove
puts frag
#=> <hello world="true"/>

# Alternatively, to remove all PIs everywhere, including inside child nodes
frag.xpath('processing-instruction()|.//processing-instruction()').remove

 


If you have a Builder object, do either of:

builder = Nokogiri::XML::Builder.new{ |xml| xml.hello(world:"true") }

puts builder.to_xml
#=> <?xml version="1.0"?>
#=> <hello world="true"/>

puts builder.doc.root.to_xml
#=> <hello world="true"/>

formatted_no_decl = Nokogiri::XML::Node::SaveOptions::FORMAT +
                    Nokogiri::XML::Node::SaveOptions::NO_DECLARATION

puts builder.to_xml save_with:formatted_no_decl
#=> <hello world="true"/>
Larrikin answered 21/11, 2011 at 22:23 Comment(6)
it used to take me to #attributes-i-<something> instead of #attributes. Looking at the history now, I don't see that reference anymore. If it's my mistake, please disregard/undo it.Berneicebernelle
See also the correct solutionGrogan
Thank you, @onions; I've added your findings to this answer, and also upvoted your answer and question.Larrikin
Using NO_DECLARATION causes the output to lose all formatting, which kinds sucks (newlines and indentation).Airsick
@Airsick Thanks for pointing this out. So what you really want is to use save_with: (Nokogiri::XML::Node::SaveOptions::NO_DECLARATION + Nokogiri::XML::Node::SaveOptions::FORMAT)...or, very ugly, just save_with:3.Larrikin
@Larrikin I used :indent => 4 and it also worked fine.Airsick
H
0

Here is how to do this in rails: skip_instruct: true

 ['array of', 'strings'].to_xml skip_instruct: true, skip_types: true

 => "<strings>\n  <string>array of</string>\n  <string>strings</string>\n</strings>\n"
Highcolored answered 16/7, 2015 at 9:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.