Ordering XML Attributes with Hpricot?

L

Lance Pollard

Hey,

Is there a way to organize/print out the xml attributes using Hpricot,
or do I have to run through the xml file again and replace patterns?

I would like to be able to say "put this attribute first, put this
attribute next ...", so I can say, I want this:

<node id="name" property="value"/>

not this:

<node property="value" id="name"/>

Since the attributes are kept in a hash there's no order to them, so
they appear in seemingly random order, but it's the same random order
consistently.

Any ideas how to do that?

And is there a way to say "after two attributes, make a new line". So I
can print out xml that can be edited by humans like code.

Thanks,
Lance
 
A

Axel Etzold

Dear Lance,
Since the attributes are kept in a hash there's no order to them, so
they appear in seemingly random order, but it's the same random order
consistently.

Any ideas how to do that?

a Hash can be sorted to give an Array with Hash#sort :

http://ruby-doc.org/core/classes/Hash.html#M002865

And is there a way to say "after two attributes, make a new line". So I
can print out xml that can be edited by humans like code.

You can then iterate through the Array with Array#each_with_index,
eg.

my_array.each_with_index{|x,i|
 
A

Axel Etzold

Dear Lance,

I accidentally hit the "send" button too early:
Since the attributes are kept in a hash there's no order to them, so
they appear in seemingly random order, but it's the same random order
consistently.

Any ideas how to do that?

a Hash can be sorted to give an Array with Hash#sort :

http://ruby-doc.org/core/classes/Hash.html#M002865

And is there a way to say "after two attributes, make a new line". So I
can print out xml that can be edited by humans like code.

You can then iterate through the Array with Array#each_with_index,
eg.

my_array.each_with_index{|x,i| if i%2==0 ; p x + "\n"; else p x; end}

Best regards,

Axel
 
L

Lance Pollard

This means though I have to do two passes on the XML:

1) Modify the nodes with data the way nokogiri or hpricot do it (xpath
and whatnot)
2) Format the xml using regular expression on pure strings, not using
the xml parsing engines.

Is that correct?

Thanks,
Lance
 
A

Axel Etzold

-------- Original-Nachricht --------
Datum: Fri, 25 Sep 2009 10:54:03 +0900
Von: Lance Pollard <[email protected]>
An: (e-mail address removed)
Betreff: Re: Ordering XML Attributes with Hpricot?
This means though I have to do two passes on the XML:

1) Modify the nodes with data the way nokogiri or hpricot do it (xpath
and whatnot)
2) Format the xml using regular expression on pure strings, not using
the xml parsing engines.

Is that correct?

Lance,

I remember that Hpricot and Nokogiri both have pretty_print methods, but I have never used them. Also, I don't know whether "pretty" can be defined so that everybody agrees :)

Best regards,

Axel
 
R

Robert Klemme

2009/9/25 Lance Pollard said:
This means though I have to do two passes on the XML:

1) Modify the nodes with data the way nokogiri or hpricot do it (xpath
and whatnot)
2) Format the xml using regular expression on pure strings, not using
the xml parsing engines.

Is that correct?

I would not work on the output XML via String replacements. I would
rather adjust the output process. For example, if you would be
working with REXML you could implement a Formatter which outputs
attributes in a particular order. I don't know whether this can be
done with Nokogiri or Hpricot as well or as easily.

Kind regards

robert


require 'rexml/document'

class OrderedAttributes < REXML::Formatters::pretty
def write_element(elm, out)
att = elm.attributes

class <<att
alias _each_attribute each_attribute

def each_attribute(&b)
to_enum:)_each_attribute).sort_by {|x| x.name}.each(&b)
end
end

super(elm, out)
end
end

doc = REXML::Document.new(DATA.read)

fmt = REXML::Formatters::pretty.new
fmt.write(doc, $stdout)
puts

fmt = OrderedAttributes.new
fmt.write(doc, $stdout)
puts

__END__
<foo battr="1" aattr="2" cattr="3">
</foo>
 
L

Lance Pollard

require 'rexml/document'
class OrderedAttributes < REXML::Formatters::pretty
def write_element(elm, out)
att = elm.attributes

class <<att
alias _each_attribute each_attribute

def each_attribute(&b)
to_enum:)_each_attribute).sort_by {|x| x.name}.each(&b)
end
end

super(elm, out)
end
end

doc = REXML::Document.new(DATA.read)

fmt = REXML::Formatters::pretty.new
fmt.write(doc, $stdout)
puts

fmt = OrderedAttributes.new
fmt.write(doc, $stdout)
puts

__END__
<foo battr="1" aattr="2" cattr="3">
</foo>

Thanks a lot Robert, I will try that out immediately.

Best,
Lance
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top