Rexml - pretty print with text inline and child tags indented
Asked Answered
E

1

9

I'm building an xml doc with REXML, and want to output to text in a particular way. The doc is a list of CuePoint tags, and the ones that i've generated with Element.new and add_element are all mushed together into a single line like this: (stackoverflow has split them over two lines here but imagine the following is all on one line):

<CuePoint><Time>15359</Time><Type>event</Type><Name>inst_50</Name></CuePoint><CuePoint><Time>16359</Time><Type>event</Type><Name>inst_50</Name></CuePoint>

When i save them out to file, i want them to look like this:

<CuePoint>
  <Time>15359</Time>
  <Type>event</Type>
  <Name>inst_50</Name>
</CuePoint>

<CuePoint>
  <Time>16359</Time>
  <Type>event</Type>
  <Name>inst_50</Name>
</CuePoint>

I tried passing the .write function a value of 2, to indent them: this produces the following:

xml.write($stdout, 2) produces

<CuePoint>
  <Time>
    15359
  </Time>
  <Type>
    event
  </Type>
  <Name>
    inst_50
  </Name>
</CuePoint>
<CuePoint>
  <Time>
    16359
  </Time>
  <Type>
    event
  </Type>
  <Name>
    inst_50
  </Name>
</CuePoint>

This is unwanted because it has inserted whitespace into the contents of the tags which just have text. ie the contents of the Name tag is now "\n inst_50\n " or something. This is going to blow up the app that reads the xml.

Does anyone know how i can format the output file the way i want it?

Grateful for any advice, max

EDIT - I just found the answer on ruby-forum, via another StackOverflow post: http://www.ruby-forum.com/topic/195353

  formatter = REXML::Formatters::Pretty.new
  formatter.compact = true
  File.open(@xml_file,"w"){|file| file.puts formatter.write(xml.root,"")}

This produces results like

<CuePoint>
  <Time>33997</Time>
  <Type>event</Type>
  <Name>inst_45_off</Name>
</CuePoint>
<CuePoint>
  <Time>34080</Time>
  <Type>event</Type>
  <Name>inst_45</Name>
</CuePoint>

There's no extra line between the CuePoint tags but that's fine for me. I'm leaving this question up here in case anyone else stumbles across it.

Everett answered 19/1, 2011 at 16:34 Comment(0)
T
18

You need to set the formatter's compact property to true, but you can only do that by setting a separate formatter object first, then using that to do your writing rather than calling the document's own write method.

formatter = REXML::Formatters::Pretty.new(2)
formatter.compact = true # This is the magic line that does what you need!
formatter.write(xml, $stdout)
Theresa answered 19/1, 2011 at 16:45 Comment(2)
Thanks dmarkow, this was the same as i figured out after posting (see my edit).Everett
Note that you also have to set formatter.width = <very high number> if you want to avoid that longer lines of text nodes get wrapped.Realistic

© 2022 - 2024 — McMap. All rights reserved.