How to sort the file contents by counrty names

I want to sort the file contents by country names :

require ‘nokogiri’

file_str = “C:\Users\TAX PAGE PROD\Production_validation.xml”
File.open(file_str) do |f|
doc = Nokogiri::XML(f)
@node_set = doc.xpath("//field[@property=‘dummyProperty’]")
end
trgt_file_path = “C:\Users\Tax form
Demo\option_value_country_demo.txt”

File.open(trgt_file_path,“w”) do |f|
@node_set.each do |node|
country = node.at_xpath("./arg0")[‘key’][/TAX ID for Country
(.*)/i,1]
option_value = node.xpath("./var[last()]/var-value").text
f.puts(“option value of #{country} is #{option_value}”)
end
end

The below code I don’t think elegant, although it worked.

sorted_ary = File.foreach(trgt_file_path).map{|line| line.split(" ")
}.sort_by{ |a| a[3] }

File.open(trgt_file_path,“w”) do |f|
sorted_ary.each do |ary|
f.puts(ary.join(" "))
end
end

Can I get help to make it elegant ?

I don’t think map is necessary. Since all you’re doing in map is split,
and you join after sorting, you can just sort by the Regexp capture.

e.g.
sort_by{ |line| line.s.scan(/([^\s])/)[4] }

Joel P. wrote in post #1132517:

I don’t think map is necessary. Since all you’re doing in map is split,
and you join after sorting, you can just sort by the Regexp capture.

e.g.
sort_by{ |line| line.s.scan(/([^\s])/)[4] }

What is line.s ?

I am thinking if that sorting can be done inside the file itself,
without creating any array… Is it possible ?

Oops, “s” was the variable I was using in IRB. It should just be
“line.scan”.

You need to read, sort, and write. There’s no way to sort the file
without read and write operations.

And I forgot to put a “+” at the end of the Regexp… Well, it’s just a
demo, you’ll need to write something which fits your specific usage
case.

On Wed, Jan 8, 2014 at 12:27 PM, Arup R. [email protected]
wrote:

Demo\option_value_country_demo.txt"

File.open(trgt_file_path,“w”) do |f|
@node_set.each do |node|
country = node.at_xpath(“./arg0”)[‘key’][/TAX ID for Country
(.*)/i,1]
option_value = node.xpath(“./var[last()]/var-value”).text
f.puts(“option value of #{country} is #{option_value}”)
end
end

Here’s a generic approach:

require ‘nokogiri’

dom = File.open(“x.xml”, “rb”){|io| Nokogiri.XML(io)}

dom = Nokogiri.XML(DATA.read)

sorting

items = dom.xpath(‘//foo’)
parent = items.first.parent
items.each(&:unlink)
items.sort_by {|n| Integer(n.text())}.each {|n| parent << n}

output formatting for nice presentation

xslt = Nokogiri::XSLT(<<XSL)
<xsl:stylesheet version=“1.0”
xmlns:xsl=“XSLT Namespace”>
<xsl:output method=“xml” encoding=“UTF-8” indent=“yes”/>
<xsl:strip-space elements=“*”/>
<xsl:template match=“/”>
<xsl:copy-of select=“.”/>
</xsl:template>
</xsl:stylesheet>
XSL

puts xslt.transform(dom)

END

<?xml encoding="UTF-8"?> 123 99 34

You just need to modify XPath selecting items and the contents of the
sort_by block.

Kind regards

robert