Xml parsing in ruby

Hi,

I am very new to ruby programming and therefore, facing problem in xml
parsing in ruby. The problem is to parse an xml file(xmlfile.xml) in
ruby that should generate a code which should look like as under:

typedef int[0,2] StateTC;
const StateTC TC_ACTIVE = 0;
const StateTC TC_COMPLETING = 1;
const StateTC TC_ENDED = 2;

StateTC stTC = TC_ACTIVE;

typedef int[0,2] StateP;
const StateP P_ACTIVE = 0;
const StateP P_COMPLETING = 1;
const StateP P_ENDED = 2;

StateP stP = P_ACTIVE;

typedef int[0,1] MsgsTC;
const MsgsTC PREPARE_TC = 0;
bool msgsTc[MsgsTC];

typedef int[0,1] MsgsP;
const MsgsP COMPLETE_P = 0;
bool msgsP[MsgsP];

I attach 2 files: xmlfile(source file), rubyfile(my try). Can you please
help me in writing ruby code that generates output as shown above from
xmlfile.

Thanks in advance.

Regards,
Salim

Have you looked into nokogiri?

Sent from my iPhone

Daniel Zd wrote in post #968678:

Have you looked into nokogiri?

Sent from my iPhone

No, I could not find it. When did you sent it?

Salim Reza wrote in post #968699:

Daniel Zd wrote in post #968678:

Have you looked into nokogiri?

Sent from my iPhone

No, I could not find it. When did you sent it?

Ok. I tried to look into nokogiri but I could not solve my problem yet.
Perhaps, i still need help.

Salim,

Why the second “<role name” = par?
But there’s const StateP (P not PAR).
Wouldn’t it be StatePAR ?

If PAR, something like this would solve half of the problem.

It’s still ugly code… but, we can improve it together.

require ‘rexml/document’
include REXML
file = File.new(“xmlfile.xml”)
doc = Document.new(file)

doc.elements.each(“protocol/role”) do |r|
role = r.attributes[“name”].upcase
states = r.get_elements(“states/state”)

First line

stm = “typedef int[0,%d] State%s;\n” % [states.size-1, role]

states.each_with_index do |s, ix|
# One line for each state
state = “const State%s %s = %d;\n” % [ role, s.text.upcase, ix]
stm << state
end
puts stm
puts
end

But, if it’s really “P” then we could get the “P” “regexping” the
states for the part before the underline signal.

What language is this?

On 15.12.2010 21:28, Salim Reza wrote:

Salim Reza wrote in post #968699:

Daniel Zd wrote in post #968678:

Have you looked into nokogiri?

No, I could not find it. When did you sent it?

Ok. I tried to look into nokogiri but I could not solve my problem yet.
Perhaps, i still need help.

Typically you’ll get more and better answers if you ask more specific
questions. What does not work in your code? What error do you see?
These kinds of things.

Cheers

robert

Salim,

I have “finished” the script.
It’s getting uglier at each interaction. (needs refactoring)
But, it seems to work well.

I renamed to xml2uppall.rb.
There’s 2 xml. The second is a modified version just for put the
script to proof.
Each cpp file corresponds to an xml file.

Tell me if it works for you.

Tell me if you don’t understand any part of the code.

Abinoam Jr.

Abinoam Jr. wrote in post #968720:

Salim,
Hi Abinoam,

I am really grateful to you for your immense help.

Why the second “<role name” = par?
But there’s const StateP (P not PAR).
Wouldn’t it be StatePAR ?

You are right. It should be “PAR” instead of “P” (that is: StatePAR) in
order to maintain the consistency and easiness.

I have extended your help_code to messages. However, output result
appends all messages to each role, whereas each role(TC and PAR) should
have its own messages list. For example: I need:
typedef int[0,1] MsgsTC;
const MsgsTC PREPARE_TC = 0;
bool msgsTc[MsgsTC]; as an out put. But my output shows:

typedef int[0,1] MsgsTC;
const MsgsTC PREPARE_TC = 0;
const MsgsTC COMPLETE_PAR = 1; that means it also appends message from
the PAR role which should not happen. I do not understand how do
decrease ranges. Though I have tried.

I attach again revised xmlfile.xml and rubyfile.rb. Please help.

What language is this?
This is C/C++ based language used by Uppaal tool.

Thanks once again for help.

(ARGV[0].nil?) ? (“xmlfile.xml”) : (ARGV[0])

The first ARGV is nil? The user didn’t suplied any command line
argument?
So use the “xmlfile.xml” as default.
Else, use the filename suplied by the user.

Try “xml2uppaal.rb xmlfile2.xml”.

Regexp.new(/\w*_(\w*)/)

Search for something in the form of (anyword) + an underline +
(anyword) and “save” the word after the underline.

“\w*_(\w*)”

\w (any word character)

  • 1 or more times
    () delimiter for retrieving it after the search.

Play around with this site.

Abinoam Jr. wrote in post #968849:

Salim,

I have “finished” the script.
It’s getting uglier at each interaction. (needs refactoring)
But, it seems to work well.

I renamed to xml2uppall.rb.
There’s 2 xml. The second is a modified version just for put the
script to proof.
Each cpp file corresponds to an xml file.

Tell me if it works for you.

Tell me if you don’t understand any part of the code.

Abinoam Jr.

Hi Abinoam,

It works as intended. Thanks for the help. I have understood most of the
code. Except: ARGV[0].nil? ? “xmlfile.xml” : ARGV[0] and
Regexp.new(/\w*_(\w*)/). I am trying to take a look about these from
tutorials.

Thanks once again.

Abinoam Jr. wrote in post #968957:

(ARGV[0].nil?) ? (“xmlfile.xml”) : (ARGV[0])

The first ARGV is nil? The user didn’t suplied any command line
argument?
So use the “xmlfile.xml” as default.
Else, use the filename suplied by the user.

Try “xml2uppaal.rb xmlfile2.xml”.

Regexp.new(/\w*_(\w*)/)

Search for something in the form of (anyword) + an underline +
(anyword) and “save” the word after the underline.

“\w*_(\w*)”

\w (any word character)

  • 1 or more times
    () delimiter for retrieving it after the search.

Play around with this site.
http://www.rubular.com/

Thanks Abinoam.

Regards,
Salim