# REXML, each\_element and XPath

**URL:** <https://www.ruby-forum.com/t/rexml-each-element-and-xpath/54551>\
**Category:** Ruby\
**Created:** [March 8, 2006, 11:11am UTC](https://www.ruby-forum.com/t/rexml-each-element-and-xpath/54551 "2006-03-08T11:11:31Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Thibaut\_BarrSSSSre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6de8d8/32.png) [@Thibaut\_BarrSSSSre](https://www.ruby-forum.com/u/Thibaut_BarrSSSSre)\
**Post date:** [March 8, 2006, 11:11am UTC](https://www.ruby-forum.com/t/rexml-each-element-and-xpath/54551/1 "2006-03-08T11:11:31Z")

</div>

Hi!

while playing with REXML I try to use each\_element with an x-path  
expression involving an attribute (doc/element/@attribute) but can’t  
get it to work this way (it works perfectly fine with both XPath.each  
and each\_element applied on doc/element without @attribute).

here’s my test suite to illustrate this, is there some obvious mistake  
that I cannot see ? I’ve read in older posts that each\_element did not  
recurse, would it be the explanation ?

any insight most welcome!

kind regards

Thibaut

============

require “test/unit”  
require “rexml/document”  
include REXML

class XmlTests \< Test::Unit::TestCase

# fail

def test\_each\_element\_with\_attribute  
count = 0  
@doc.each\_element(“doc/element/@attribute”) { |n| count = count+1 }  
assert\_equal 1,count  
end

# pass

def test\_each\_element\_without\_attribute  
count = 0  
@doc.each\_element(“doc/element”) { |n| count = count+1 }  
assert\_equal 1,count  
end

# pass

def test\_xpath  
count = 0  
XPath.each(@doc,“doc/element/@attribute”) { |n| count = count+1 }  
assert\_equal 1,count  
end

def setup  
@doc = Document.new(\<\<EOF  
  
  
  
EOF  
)  
end

end

---

<div class="post-metadata">

**Author:** ![Thibaut\_BarrSSSSre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6de8d8/32.png) [@Thibaut\_BarrSSSSre](https://www.ruby-forum.com/u/Thibaut_BarrSSSSre)\
**Post date:** [March 8, 2006, 11:51am UTC](https://www.ruby-forum.com/t/rexml-each-element-and-xpath/54551/2 "2006-03-08T11:51:10Z")

</div>

It seems that when xpathing with an attribute @doc.each\_element  
returns an array containting the attributes:

irb(main):009:0\> @doc = REXML::Document.new(\<\<EOF  
irb(main):010:1" \</  
doc\>  
irb(main):011:1" EOF  
irb(main):012:1\> )  
irb(main):016:0\> @doc.each\_element(“doc/element/@attribute”)  
=\> [attribute=‘value’, attribute=‘value’]

Not sure if this is a bug. I’m using the version of REXML that comes  
with 1.8.2 on Windows.

Farrel

---

<div class="post-metadata">

**Author:** ![Thibaut\_BarrSSSSre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6de8d8/32.png) [@Thibaut\_BarrSSSSre](https://www.ruby-forum.com/u/Thibaut_BarrSSSSre)\
**Post date:** [March 8, 2006, 12:45pm UTC](https://www.ruby-forum.com/t/rexml-each-element-and-xpath/54551/3 "2006-03-08T12:45:53Z")

</div>

I’ve done some experimentation and I think the problem is as follows.  
/doc/element/@attribute is a search for the attribute node, not the  
element, so using it with doc.each\_element isn’t strictly  
‘semantically’ correct. If you want to find an element with an  
attribute you should use the /doc/element[@attribute] xpath string.

irb(main):002:0\> doc = REXML::Document.new(\<\<EOF  
irb(main):003:1" "  
irb(main):004:1" EOF  
irb(main):005:1\> )  
irb(main):006:0\> doc.each\_element("/doc/element[@attribute]"){|n| puts  
[“attribute”]}  
value  
=\> []

---

<div class="post-metadata">

**Author:** ![Thibaut\_BarrSSSSre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/6de8d8/32.png) [@Thibaut\_BarrSSSSre](https://www.ruby-forum.com/u/Thibaut_BarrSSSSre)\
**Post date:** [March 8, 2006, 1:40pm UTC](https://www.ruby-forum.com/t/rexml-each-element-and-xpath/54551/4 "2006-03-08T13:40:52Z")

</div>

Hi Farrel and thanks for your feedback!

I’ve searched more and finally found a note here:  
[http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/classes/REXML/Elements.html#M002906](http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/classes/REXML/Elements.html#M002906)

“Note that XPaths are automatically filtered for Elements, so that  
non-Element children will not be yielded”

So basically that’s what you said : Attribute instances (non-Element)  
cannot be retrieved directly through each\_element.

I either have to seek for elements then grab the attribute like you  
did, or stick with XPath.each which does the job pretty well.

thanks!

Thibaut
