Forum: Ruby REXML, each_element and XPath

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Thibaut Barrère (Guest)
on 2006-03-08 12:11
(Received via mailing list)
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
		<doc>
			<element attribute="value"/>
		</doc>
EOF
    )
  end

end
Farrel L. (Guest)
on 2006-03-08 12:51
(Received via mailing list)
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><element attribute="value"/><element
attribute="value"/></
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
Farrel L. (Guest)
on 2006-03-08 13:45
(Received via mailing list)
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" <doc><element attribute="value"/></doc>"
irb(main):004:1" EOF
irb(main):005:1> )
irb(main):006:0> doc.each_element("/doc/element[@attribute]"){|n| puts
["attribute"]}
value
=> [<element attribute='value'/>]
Thibaut Barrère (Guest)
on 2006-03-08 14:40
(Received via mailing list)
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/c...

"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
This topic is locked and can not be replied to.