# REXML and XPath

**URL:** <https://www.ruby-forum.com/t/rexml-and-xpath/103360>\
**Category:** Rails\
**Created:** [May 4, 2007, 6:41pm UTC](https://www.ruby-forum.com/t/rexml-and-xpath/103360 "2007-05-04T18:41:19Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![fipa](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/9e8a1a/32.png) [@fipa](https://www.ruby-forum.com/u/fipa)\
**Post date:** [May 4, 2007, 6:41pm UTC](https://www.ruby-forum.com/t/rexml-and-xpath/103360/1 "2007-05-04T18:41:19Z")

</div>

Hi. I’m working with XML and REXML and I could use some help in two  
particular issues:  
First, I want to display a REXML::Document object. I’m creating the  
object from a string that contains a valid xml, something like:

 Gecamin Paseo Bulnes 197 Fernando Poblete ..... 

And I want to produce HTML as follows:

Name: Gecamin

Address: Paseo Bulnes 197

 Employees 

First Name: Fernando

Last Name: Poblete

 .... ...

The second thing is that I’m working with two versions of a same record,  
each one in a different REXML::Document object. So I have  
@old\_record\_xml and @new\_record\_xml and want to compare them in order to  
indicate which fields has changed from old version to new version. So if  
an employee’s first name has been changedn I want to produce HTML like

First Name: Fer

I know XPath is the best answer but I haven’t been able to figure it  
out. Could anyone give me some tips? Thanks.

---

<div class="post-metadata">

**Author:** ![fipa](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/9e8a1a/32.png) [@fipa](https://www.ruby-forum.com/u/fipa)\
**Post date:** [May 5, 2007, 6:45am UTC](https://www.ruby-forum.com/t/rexml-and-xpath/103360/2 "2007-05-05T06:45:19Z")

</div>

For your first problem, it sounds like you should be using XSLT:  
[http://greg.rubyfr.net/pub/packages/ruby-xslt/files/README.html](http://greg.rubyfr.net/pub/packages/ruby-xslt/files/README.html)

For your second, I’ve never heard of XPath being used for this, but I  
could be wrong. It sounds like you’ll just have to write your own  
compare function that will emit nodes that have changed.

On May 5, 12:41 am, Fernando P. \<rails-mailing-l…@andreas-

---

<div class="post-metadata">

**Author:** ![fipa](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/9e8a1a/32.png) [@fipa](https://www.ruby-forum.com/u/fipa)\
**Post date:** [May 5, 2007, 5:13pm UTC](https://www.ruby-forum.com/t/rexml-and-xpath/103360/3 "2007-05-05T17:13:58Z")

</div>

Fernando P. wrote:

> Hi. I’m working with XML and REXML and I could use some help in two  
> particular issues:  
> First, I want to display a REXML::Document object.

Last time I checked, Ruby had incomplete native XSLT support. You need  
to  
get either msxsl.exe by Microsoft or xsltproc by everyone else. Then  
pipe  
your XML thru an XSLT template to re-render everything in XHTML.

Below my sig is a snip of code that detects which one you have and calls  
it  
correctly.

To diff XML, you could google for “diff XML”, “XMLunit”, or “XSLTunit”.  
I  
have not tried either, but as diffing content is a major aspect of  
testing,  
the XSLTunit ought to show how to do it.

–  
Phlip  
[Test Driven Ajax (on Rails) [Book]](http://www.oreilly.com/catalog/9780596510657/)  
“Test Driven Ajax (on Rails)”  
assert\_xpath, assert\_javascript, & assert\_ajax

$win32Exts = %w{.exe .com .bat}

# Adapted from Michael G.'s FileWhich on RubyGarden

def which(prog, path=ENV[‘PATH’])

path.split(File::PATH\_SEPARATOR).each {|dir|

# Windows checks against specific extensions

if File::ALT\_SEPARATOR  
ext = $win32Exts.find{|ext|  
if prog.include?(‘.’) # Assume extension already included  
f = File.join(dir,prog)  
else  
f = File.join(dir,prog+ext)  
end  
File.executable?(f) && !File.directory?(f)  
}  
if ext  
# Use backslashes, not forward slashes  
if prog.include?(‘.’) # Assume extension already included  
f = File.join( dir, prog ).gsub(///,‘\’)  
else  
f = File.join( dir, prog + ext ).gsub(///,‘\’)  
end  
return f  
end  
else  
f = File.join(dir,prog)  
# Avoid /usr/lib/ruby, for example  
if File.executable?(f) && !File.directory?(f)  
return File::join( dir, prog )  
end  
end  
}  
nil

end

def callXsl(xslFile, xmlFile, param = {})

msxsl = which(‘msxsl’)  
xsltproc = which(‘xsltproc’)

if xsltproc != nil then  
params = ‘’

```
param.each { |p,v|
  params += "--param #{p} \"'#{v}'\" "
  }

xhtml = `#{xsltproc} #{params} #{xslFile} #{xmlFile} 2>&1`
return xhtml

```

elsif msxsl != nil then  
params = ‘’

```
param.each { |p,v|
  params += p
  params += '="'
  params += v
  params += '" '
  }

msxsl.gsub!'\\\\', '/'
cmd = "#{msxsl} #{xmlFile} #{xslFile} #{params}"
xhtml = `#{cmd} 2>&1`
return xhtml

```

else  
return ‘please install either msxsl or xsltproc’  
end

end

def \_Transform(xmlFile, xslFile, param)  
return callXsl(xslFile, xmlFile, param = {})  
end
