tags:

views:

439

answers:

2

I try to generate such XML using REXML

<root>
  <add key='foo' value='bar'/>
</root>

But what I get is (notice that key/value order)

<root>
  <add value='bar' key='foo'/>
</root>

Code:

require 'rexml/document'
include REXML

doc = Document.new
doc.add_element('root')
el = doc.root.add_element('add')
el.add_attribute('key', 'foo')
el.add_attribute('value', 'bar')
puts doc

It does not matter if I write:

el.add_attribute('key', 'foo')
el.add_attribute('value', 'bar')

or

el.add_attribute('value', 'bar')
el.add_attribute('key', 'foo')

result is the same. Looks like REXML uses some dictionary to keep the attributes...

Can I enforce the desired order: key/value?

+8  A: 

In XML, it doesn't matter what order the attributes are in. If you have some piece of XML processing code where it does matter, then I would suggest that code was buggy.

From the XML spec here, note the phrase: "Note that the order of attribute specifications in a start-tag or empty-element tag is not significant".

In answer to your specific question on whether you can enforce a certain order, I don't believe so. I've never actually tried to do it (since it's unnecessary) but it seems unlikely the REXML people would waste time implementing such a non-feature :-). Since the key/value pairs are stored as a hash, their order is likely to be random (as far as you could tell from the alphabetic sequence of the keys).

Of course, since Ruby comes with the source code for REXML, you could (if desperate) replace or augment the included copy with your own version (REXML2 ?).

Since you're doing a simple puts, it's probably using the pretty formatter so check the start of the write_element code in src/rexml/formatters/pretty.rb where it performs the "node.attributes.each_attribute do |attr|" - you may find it's as simple as sorting that list before processing the elements.

You may also want to suggest to the developers (see here for the mailing list or here for bug reports and enhancement requests) that they make this an option in a future release but, if I were them, I'd simply say it was unnecessary.

paxdiablo
Sure, the order does not matter from machine perspective. I need it for readability only. Actually I have to modify config file, and whould like to preserve formatting as much as possible.
alex2k8
See updates on possible approaches (basically either forking for local use or trying to convince developers to add this feature).
paxdiablo
+1  A: 

If you're modifying a config file and formatting is important, then it might be easier to read it in via REXML but modify via regexps.

Also, keep in mind that generating a lot of XML via REXML is incredibly slow. I had a site that had to both read and write a lot of XML; I found that for reading, REXML was fast enough, but for writing I had to use libxml. And actually, libxml was such a bear to install and the ruby libraries for it so immature, that I ended up using erb to just replace certain parts of already-written XML docs.

Good luck!

Sarah Mei