# Can you search in REXML by attributes?

**URL:** <https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301>\
**Category:** ruby-talk\
**Created:** [1 April 2011 00:53 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301 "2011-04-01T00:53:43Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [1 April 2011 00:53 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/1 "2011-04-01T00:53:43Z")

</div>

Hello and thank you to all the wonderful and helpful people at this  
forum. I am trying to figure out how to search through an XML file and  
grab information. I have been reading the REXML tutorials but could not  
see an answer to my problem in them  
([http://www.germane-software.com/software/rexml/docs/tutorial.html](http://www.germane-software.com/software/rexml/docs/tutorial.html)).  
The problem is I need to search by an attribute (in this case the ref)  
and cannot figure out how. Here is a snippet of the XML I am trying to  
extract information from:

\<IfcWallStandardCase id="i1677"\>  
&nbsp;&nbsp;\<ObjectPlacement\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
&nbsp;&nbsp;\</ObjectPlacement\>  
\</IfcWallStandardCase\>

\<IfcAxis2Placement3D id="i1671"\>  
&nbsp;&nbsp;\<Location\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
&nbsp;&nbsp;\</Location\>  
\</IfcAxis2Placement3D\>

\<IfcCartesianPoint id="i1667"\>  
&nbsp;&nbsp;\<Coordinates id="i1670" exp:cType="list"\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
&nbsp;&nbsp;\</Coordinates\>  
\</IfcCartesianPoint\>

So basically I have to start with IfcWallStandardCase and from there  
work my way through the "ref"'s until I get to the 3 IfcLengthMeasures.  
I know how to grab the first ref "i1671" using:  
XPath.match(doc,"/IfcWallStandardCase/ObjectPlacement/IfcLocalPlacement")  
and some additional code.

My problem is I cannot figure out how to use this "i1671" to search the  
xml and grab the next ref. This ref is the only thing linking the items  
together, so it is the only thing that I can use.

Is it possible to search a document by using an attribute, and if so  
how? In this case to use the ref, "i1671" to search the document for  
where it is used as id="i1671" so I can grab the next ref from there and  
so on. Any help would be greatly appreciated.

Thank you all.

Sincerely,  
Kyle

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![7stud](https://avatars.discourse-cdn.com/v4/letter/7/57b2e6/32.png) [@7stud](https://rubytalk.org/u/7stud)\
**Post date:** [1 April 2011 01:27 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/2 "2011-04-01T01:27:27Z")

</div>

I think this is the XPath for the elements you want:

//IfcLengthMeasure[@id = 'i1671']

...whether REXML fully supports XPath is another question. Try it and  
see if it works.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![7stud](https://avatars.discourse-cdn.com/v4/letter/7/57b2e6/32.png) [@7stud](https://rubytalk.org/u/7stud)\
**Post date:** [1 April 2011 01:45 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/3 "2011-04-01T01:45:54Z")

</div>

...the xpath:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//\*[@id = 'i1671']

finds all tags with an id attribute whose value is 'i1671'. You might  
want to check out an XPath tutorial to get specifics on XPath, e.g.:

[http://www.w3schools.com/xpath/xpath\_syntax.asp](http://www.w3schools.com/xpath/xpath_syntax.asp)

However, it doesn't necessarily mean that REXML will support the  
particular xpath feature you try.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [1 April 2011 08:12 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/4 "2011-04-01T08:12:45Z")

</div>

It is not entirely clear what you want. Do you want to look for all  
"ref" instances and find elements they are referring to? Or do you  
want to do some kind of graph traversal where you start with a  
particular element and follow every ref attribute?

If the latter you can for example do a BFS.

10:11:30 Temp$ ./rx.rb  
--- VISIT:  
\<IfcAxis2Placement3D id='i1671'\>  
\<Location\>  
&nbsp;&nbsp;&nbsp;\<IfcCartesianPoint xsi:nil='true' ref='i1667'/\>  
\</Location\>  
\</IfcAxis2Placement3D\>  
--- VISIT:  
\<IfcCartesianPoint id='i1667'\>  
\<Coordinates exp:cType='list' id='i1670'\>  
&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos='0'\>117.4\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos='1'\>119.7\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos='2'\>0.\</IfcLengthMeasure\>  
\</Coordinates\>  
\</IfcCartesianPoint\>  
10:11:43 Temp$ cat -n rx.rb  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 #!/bin/env ruby19  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3 require 'rexml/document'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5 doc = REXML::Document.new(DATA.read)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7 # BFS  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8 queue = %w{i1671}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9  
&nbsp;&nbsp;&nbsp;&nbsp;10 until queue.empty?  
&nbsp;&nbsp;&nbsp;&nbsp;11 id = queue.shift  
&nbsp;&nbsp;&nbsp;&nbsp;12  
&nbsp;&nbsp;&nbsp;&nbsp;13 REXML::XPath.each(doc, "//\*[@id='#{id}']") do |e|  
&nbsp;&nbsp;&nbsp;&nbsp;14 puts "--- VISIT:", e  
&nbsp;&nbsp;&nbsp;&nbsp;15  
&nbsp;&nbsp;&nbsp;&nbsp;16 REXML::XPath.each(e, './/\*[@ref]') do |child|  
&nbsp;&nbsp;&nbsp;&nbsp;17 next\_id = child.attribute('ref') and queue.push(next\_id)  
&nbsp;&nbsp;&nbsp;&nbsp;18 end  
&nbsp;&nbsp;&nbsp;&nbsp;19 end  
&nbsp;&nbsp;&nbsp;&nbsp;20 end  
&nbsp;&nbsp;&nbsp;&nbsp;21  
&nbsp;&nbsp;&nbsp;&nbsp;22 \_\_END\_\_  
&nbsp;&nbsp;&nbsp;&nbsp;23 \<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
&nbsp;&nbsp;&nbsp;&nbsp;24 \<IfcWallStandardCase id="i1677"\>  
&nbsp;&nbsp;&nbsp;&nbsp;25 \<ObjectPlacement\>  
&nbsp;&nbsp;&nbsp;&nbsp;26 \<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
&nbsp;&nbsp;&nbsp;&nbsp;27 \</ObjectPlacement\>  
&nbsp;&nbsp;&nbsp;&nbsp;28 \</IfcWallStandardCase\>  
&nbsp;&nbsp;&nbsp;&nbsp;29  
&nbsp;&nbsp;&nbsp;&nbsp;30 \<IfcAxis2Placement3D id="i1671"\>  
&nbsp;&nbsp;&nbsp;&nbsp;31 \<Location\>  
&nbsp;&nbsp;&nbsp;&nbsp;32 \<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
&nbsp;&nbsp;&nbsp;&nbsp;33 \</Location\>  
&nbsp;&nbsp;&nbsp;&nbsp;34 \</IfcAxis2Placement3D\>  
&nbsp;&nbsp;&nbsp;&nbsp;35  
&nbsp;&nbsp;&nbsp;&nbsp;36 \<IfcCartesianPoint id="i1667"\>  
&nbsp;&nbsp;&nbsp;&nbsp;37 \<Coordinates id="i1670" exp:cType="list"\>  
&nbsp;&nbsp;&nbsp;&nbsp;38 \<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;39 \<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;40 \<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;41 \</Coordinates\>  
&nbsp;&nbsp;&nbsp;&nbsp;42 \</IfcCartesianPoint\>  
&nbsp;&nbsp;&nbsp;&nbsp;43 \</root\>  
10:11:47 Temp$

Kind regards

robert

[rx.rb](https://rubytalk.org/uploads/short-url/9DGQobalrZ1oocMX2fTmjYBLcXF.rb) (988 Bytes)

> **···**
>
> On Fri, Apr 1, 2011 at 2:53 AM, Kyle X. \<haebooty@yahoo.com\> wrote:
> 
> > Hello and thank you to all the wonderful and helpful people at this  
> > forum. I am trying to figure out how to search through an XML file and  
> > grab information. I have been reading the REXML tutorials but could not  
> > see an answer to my problem in them  
> > ([http://www.germane-software.com/software/rexml/docs/tutorial.html\](http://www.germane-software.com/software/rexml/docs/tutorial.html%5C)).  
> > The problem is I need to search by an attribute (in this case the ref)  
> > and cannot figure out how. Here is a snippet of the XML I am trying to  
> > extract information from:
> > 
> > \<IfcWallStandardCase id="i1677"\>  
> > \<ObjectPlacement\>  
> > \<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
> > \</ObjectPlacement\>  
> > \</IfcWallStandardCase\>
> > 
> > \<IfcAxis2Placement3D id="i1671"\>  
> > \<Location\>  
> > \<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
> > \</Location\>  
> > \</IfcAxis2Placement3D\>
> > 
> > \<IfcCartesianPoint id="i1667"\>  
> > \<Coordinates id="i1670" exp:cType="list"\>  
> > \<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
> > \<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
> > \<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
> > \</Coordinates\>  
> > \</IfcCartesianPoint\>
> > 
> > So basically I have to start with IfcWallStandardCase and from there  
> > work my way through the "ref"'s until I get to the 3 IfcLengthMeasures.  
> > I know how to grab the first ref "i1671" using:  
> > XPath.match(doc,"/IfcWallStandardCase/ObjectPlacement/IfcLocalPlacement")  
> > and some additional code.
> > 
> > My problem is I cannot figure out how to use this "i1671" to search the  
> > xml and grab the next ref. This ref is the only thing linking the items  
> > together, so it is the only thing that I can use.
> > 
> > Is it possible to search a document by using an attribute, and if so  
> > how? In this case to use the ref, "i1671" to search the document for  
> > where it is used as id="i1671" so I can grab the next ref from there and  
> > so on. Any help would be greatly appreciated.
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [1 April 2011 19:22 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/5 "2011-04-01T19:22:57Z")

</div>

Thank you Jesus, that is exactly what I was looking for and it works  
great!

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [19 April 2011 20:42 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/6 "2011-04-19T20:42:12Z")

</div>

Hello, Nokogiri has been going well for me but recently I have been  
having trouble trying to read some xml, and from my reading online I  
cannot find the proper way to write it using Nokogiri. Here are the two  
lines I am having trouble with:

1)  
\<IfcWallStandardCase id="i17855"\>  
&nbsp;&nbsp;\<Representation\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<IfcProductDefinitionShape id="i17925"\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<Representations id="i17928" exp:cType="list"\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcShapeRepresentation exp:pos="0" xsi:nil="true"  
ref="i17886"/\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcShapeRepresentation exp:pos="1" xsi:nil="true"  
ref="i17919"/\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</Representations\>  
&nbsp;&nbsp;&nbsp;&nbsp;\</IfcProductDefinitionShape\>  
&nbsp;&nbsp;\</Representation\>  
\</IfcWallStandardCase\>

I am trying to get the reference for exp:pos="1", and I had this working  
with using REXML with the following -

XPath.match( $doc, "//IfcWallStandardCase//\*[@pos='1']" )

With nokogiri I can get it to read both pos 0 and 1, using .css and  
.xpath-

$doc\_noko.css("uosNS|IfcWallStandardCase uosNS|IfcShapeRepresentation",  
{"uosNS" =\> $http})  
and  
$doc\_noko.xpath("//uosNS:IfcWallStandardCase//uosNS:IfcShapeRepresentation",  
{"uosNS" =\> $http})

But cannot figure out how to get it to read only pos=1 using either  
method and continuously get error or nil.

2)  
\<IfcDirection id="i1574"\>  
&nbsp;&nbsp;\<DirectionRatios id="i1577" exp:cType="list"\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<exp:double-wrapper pos="0"\>1.\</exp:double-wrapper\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<exp:double-wrapper pos="1"\>0.\</exp:double-wrapper\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<exp:double-wrapper pos="2"\>0.\</exp:double-wrapper\>  
&nbsp;&nbsp;\</DirectionRatios\>  
\</IfcDirection\>

The issue I am having here is that I am reading this with Nokogiri using  
.xpath and the colon in exp:double is giving me trouble since the xpath  
is written -

ref = "i1574"  
$doc\_noko.xpath("//uosNS:\*[@id='#{ref}']//uosNS:exp:double-wrapper",  
{"uosNS" =\> $http}).map {|element| element.text}

I am guessing that it would be easier to use .css here rather than  
.xpath. So I have tried using it but cannot seem to get it correct.  
Trying -

ref = "i1574"  
$doc\_noko.css("uosNS|#{ref} uosNS|exp:double-wrapper", {"uosNS" =\>  
$http}).map {|element| element.text}

As I read in a previous post that you call the ref using #{} for css,  
but this returns nil for me.

Any ideas?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [20 April 2011 07:22 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/7 "2011-04-20T07:22:50Z")

</div>

This has sufficiently deviated from the title of the thread, so to make  
the information more relevant for future searchers I am going to make a  
new post. I hope this is acceptable.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [1 April 2011 16:27 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/8 "2011-04-01T16:27:10Z")

</div>

Robert K. wrote in post #990336:

> It is not entirely clear what you want. Do you want to look for all  
> "ref" instances and find elements they are referring to? Or do you  
> want to do some kind of graph traversal where you start with a  
> particular element and follow every ref attribute?

Hi and thank you for your help. I am sorry if what I wrote was unclear.  
What my goal is is to start at a given location (in this case-  
\<IfcWallStandardCase id="i1677"\>) and eventually grab the three  
IfcLengthMeasure text values, that are associated with this  
\<IfcWallStandardCase id="i1677"\>, and put them into an array.

> If the latter you can for example do a BFS.
> 
> 10:11:30 Temp$ ./rx.rb  
> --- VISIT:  
> \<IfcAxis2Placement3D id='i1671'\>  
> \<Location\>  
> &nbsp;&nbsp;&nbsp;\<IfcCartesianPoint xsi:nil='true' ref='i1667'/\>  
> \</Location\>  
> \</IfcAxis2Placement3D\>  
> --- VISIT:  
> \<IfcCartesianPoint id='i1667'\>  
> \<Coordinates exp:cType='list' id='i1670'\>  
> &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos='0'\>117.4\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos='1'\>119.7\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos='2'\>0.\</IfcLengthMeasure\>  
> \</Coordinates\>  
> \</IfcCartesianPoint\>  
> 10:11:43 Temp$ cat -n rx.rb  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 #!/bin/env ruby19  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3 require 'rexml/document'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5 doc = REXML::Document.new(DATA.read)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7 # BFS  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8 queue = %w{i1671}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9  
> &nbsp;&nbsp;&nbsp;&nbsp;10 until queue.empty?  
> &nbsp;&nbsp;&nbsp;&nbsp;11 id = queue.shift  
> &nbsp;&nbsp;&nbsp;&nbsp;12  
> &nbsp;&nbsp;&nbsp;&nbsp;13 REXML::XPath.each(doc, "//\*[@id='#{id}']") do |e|  
> &nbsp;&nbsp;&nbsp;&nbsp;14 puts "--- VISIT:", e  
> &nbsp;&nbsp;&nbsp;&nbsp;15  
> &nbsp;&nbsp;&nbsp;&nbsp;16 REXML::XPath.each(e, './/\*[@ref]') do |child|  
> &nbsp;&nbsp;&nbsp;&nbsp;17 next\_id = child.attribute('ref') and queue.push(next\_id)  
> &nbsp;&nbsp;&nbsp;&nbsp;18 end  
> &nbsp;&nbsp;&nbsp;&nbsp;19 end  
> &nbsp;&nbsp;&nbsp;&nbsp;20 end  
> &nbsp;&nbsp;&nbsp;&nbsp;21  
> &nbsp;&nbsp;&nbsp;&nbsp;22 \_\_END\_\_  
> &nbsp;&nbsp;&nbsp;&nbsp;23 \<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;24 \<IfcWallStandardCase id="i1677"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;25 \<ObjectPlacement\>  
> &nbsp;&nbsp;&nbsp;&nbsp;26 \<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
> &nbsp;&nbsp;&nbsp;&nbsp;27 \</ObjectPlacement\>  
> &nbsp;&nbsp;&nbsp;&nbsp;28 \</IfcWallStandardCase\>  
> &nbsp;&nbsp;&nbsp;&nbsp;29  
> &nbsp;&nbsp;&nbsp;&nbsp;30 \<IfcAxis2Placement3D id="i1671"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;31 \<Location\>  
> &nbsp;&nbsp;&nbsp;&nbsp;32 \<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
> &nbsp;&nbsp;&nbsp;&nbsp;33 \</Location\>  
> &nbsp;&nbsp;&nbsp;&nbsp;34 \</IfcAxis2Placement3D\>  
> &nbsp;&nbsp;&nbsp;&nbsp;35  
> &nbsp;&nbsp;&nbsp;&nbsp;36 \<IfcCartesianPoint id="i1667"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;37 \<Coordinates id="i1670" exp:cType="list"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;38 \<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;&nbsp;39 \<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;&nbsp;40 \<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;&nbsp;41 \</Coordinates\>  
> &nbsp;&nbsp;&nbsp;&nbsp;42 \</IfcCartesianPoint\>  
> &nbsp;&nbsp;&nbsp;&nbsp;43 \</root\>  
> 10:11:47 Temp$

I will give this a try.

> Kind regards
> 
> robert

Dear 7stud. Using the XPath command:

doc = Document.new xml  
target = XPath.match(doc, "//\*[@id = 'i1671']")  
p target

It produces the following output as you said it would.  
--output:--  
[\<IfcAxis2Placement3D id='i1671'\> ... \</\>]

But I cannot figure out how to do anything with this from here to get to  
the next point, and eventually be able to grab the three values.

> **···**
>
> > On Fri, Apr 1, 2011 at 2:53 AM, Kyle X. \<haebooty@yahoo.com\> wrote:
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [4 April 2011 07:13 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/9 "2011-04-04T07:13:05Z")

</div>

Here's the same with REXML.

09:12:25 Temp$ ./rx2.rb  
Approach 1  
117.4  
119.7  
0.  
Approach 2  
117.4  
119.7  
0.  
Approach 3  
117.4  
119.7  
0.0  
09:12:45 Temp$ cat -n rx2.rb  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 #!/bin/env ruby19  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3 require 'rexml/document'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5 doc = REXML::Document.new(DATA.read)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7 puts 'Approach 1'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9 REXML::XPath.each(doc, "//\*[@id='i1671']//@ref") do |e|  
&nbsp;&nbsp;&nbsp;&nbsp;10 REXML::XPath.each(doc,  
"//\*[@id='#{e.value}']//IfcLengthMeasure/text()") do |lm|  
&nbsp;&nbsp;&nbsp;&nbsp;11 puts lm  
&nbsp;&nbsp;&nbsp;&nbsp;12 end  
&nbsp;&nbsp;&nbsp;&nbsp;13 end  
&nbsp;&nbsp;&nbsp;&nbsp;14  
&nbsp;&nbsp;&nbsp;&nbsp;15 puts 'Approach 2'  
&nbsp;&nbsp;&nbsp;&nbsp;16  
&nbsp;&nbsp;&nbsp;&nbsp;17 refs = REXML::XPath.each(doc, "//\*[@id='i1671']//@ref").map  
{|e| e.value}  
&nbsp;&nbsp;&nbsp;&nbsp;18 values = refs.map {|r| REXML::XPath.each(doc,  
"//\*[@id='#{r}']//IfcLengthMeasure/text()").to\_a}.flatten  
&nbsp;&nbsp;&nbsp;&nbsp;19 puts values  
&nbsp;&nbsp;&nbsp;&nbsp;20  
&nbsp;&nbsp;&nbsp;&nbsp;21 puts 'Approach 3'  
&nbsp;&nbsp;&nbsp;&nbsp;22  
&nbsp;&nbsp;&nbsp;&nbsp;23 refs = REXML::XPath.each(doc, "//\*[@id='i1671']//@ref").map  
{|e| e.value}  
&nbsp;&nbsp;&nbsp;&nbsp;24 values = refs.map {|r| REXML::XPath.each(doc,  
"//\*[@id='#{r}']//IfcLengthMeasure/text()").map {|x|  
x.value.to\_f}}.flatten  
&nbsp;&nbsp;&nbsp;&nbsp;25 puts values  
&nbsp;&nbsp;&nbsp;&nbsp;26  
&nbsp;&nbsp;&nbsp;&nbsp;27 \_\_END\_\_  
&nbsp;&nbsp;&nbsp;&nbsp;28 \<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
&nbsp;&nbsp;&nbsp;&nbsp;29 \<IfcWallStandardCase id="i1677"\>  
&nbsp;&nbsp;&nbsp;&nbsp;30 \<ObjectPlacement\>  
&nbsp;&nbsp;&nbsp;&nbsp;31 \<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
&nbsp;&nbsp;&nbsp;&nbsp;32 \</ObjectPlacement\>  
&nbsp;&nbsp;&nbsp;&nbsp;33 \</IfcWallStandardCase\>  
&nbsp;&nbsp;&nbsp;&nbsp;34  
&nbsp;&nbsp;&nbsp;&nbsp;35 \<IfcAxis2Placement3D id="i1671"\>  
&nbsp;&nbsp;&nbsp;&nbsp;36 \<Location\>  
&nbsp;&nbsp;&nbsp;&nbsp;37 \<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
&nbsp;&nbsp;&nbsp;&nbsp;38 \</Location\>  
&nbsp;&nbsp;&nbsp;&nbsp;39 \</IfcAxis2Placement3D\>  
&nbsp;&nbsp;&nbsp;&nbsp;40  
&nbsp;&nbsp;&nbsp;&nbsp;41 \<IfcCartesianPoint id="i1667"\>  
&nbsp;&nbsp;&nbsp;&nbsp;42 \<Coordinates id="i1670" exp:cType="list"\>  
&nbsp;&nbsp;&nbsp;&nbsp;43 \<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;44 \<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;45 \<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;46 \</Coordinates\>  
&nbsp;&nbsp;&nbsp;&nbsp;47 \</IfcCartesianPoint\>  
&nbsp;&nbsp;&nbsp;&nbsp;48 \</root\>  
09:12:46 Temp$

Have fun!

Cheers

robert

[rx2.rb](https://rubytalk.org/uploads/short-url/uVB0VHRyQY5pRY5BScYuTu70HKj.rb) (1.3 KB)

> **···**
>
> On Fri, Apr 1, 2011 at 9:22 PM, Kyle X. \<haebooty@yahoo.com\> wrote:
> 
> > Thank you Jesus, that is exactly what I was looking for and it works  
> > great!
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Jesus\_Gabriel\_y\_Gala](https://avatars.discourse-cdn.com/v4/letter/j/96bed5/32.png) [@Jesus\_Gabriel\_y\_Gala](https://rubytalk.org/u/Jesus_Gabriel_y_Gala)\
**Post date:** [1 April 2011 17:19 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/10 "2011-04-01T17:19:38Z")

</div>

I usually use Nokogiri to handle XML documents, and find css selectors  
easier than XPath. I'd do it like this:

doc = Nokogiri::XML(\<\<END  
\<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
\<IfcWallStandardCase id="i1677"\>  
\<ObjectPlacement\>  
&nbsp;&nbsp;&nbsp;\<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
\</ObjectPlacement\>  
\</IfcWallStandardCase\>

\<IfcAxis2Placement3D id="i1671"\>  
\<Location\>  
&nbsp;&nbsp;&nbsp;\<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
\</Location\>  
\</IfcAxis2Placement3D\>

\<IfcCartesianPoint id="i1667"\>  
\<Coordinates id="i1670" exp:cType="list"\>  
&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
\</Coordinates\>  
\</IfcCartesianPoint\>  
\</root\>  
END  
)

reference = doc.css("#i1671 Location IfcCartesianPoint").attribute("ref").value  
doc.css("##{reference} Coordinates IfcLengthMeasure").map {|element|  
element.text}

This returns: =\> ["117.4", "119.7", "0."]

I'm pretty sure it's easy to translate these two expressions to XPath,  
something like:

reference = REXML::XPath.first(doc,  
"//\*[@id='i1671']/Location/IfcCartesianPoint").attribute("ref").value  
elements = REXML::XPath.match(doc,  
"//\*[@id='#{reference}']/Coordinates/IfcLengthMeasure").map {|element|  
element.text}

don't know if there's a better way, but the above works for me.

Jesus.

> **···**
>
> On Fri, Apr 1, 2011 at 6:27 PM, Kyle X. \<haebooty@yahoo.com\> wrote:
> 
> > Robert K. wrote in post #990336:
> > 
> > > On Fri, Apr 1, 2011 at 2:53 AM, Kyle X. \<haebooty@yahoo.com\> wrote:
> > > 
> > > It is not entirely clear what you want. Do you want to look for all  
> > > "ref" instances and find elements they are referring to? Or do you  
> > > want to do some kind of graph traversal where you start with a  
> > > particular element and follow every ref attribute?
> > 
> > Hi and thank you for your help. I am sorry if what I wrote was unclear.  
> > What my goal is is to start at a given location (in this case-  
> > \<IfcWallStandardCase id="i1677"\>) and eventually grab the three  
> > IfcLengthMeasure text values, that are associated with this  
> > \<IfcWallStandardCase id="i1677"\>, and put them into an array.
> > 
> > > If the latter you can for example do a BFS.
> > > 
> > > 10:11:30 Temp$ ./rx.rb  
> > > --- VISIT:  
> > > \<IfcAxis2Placement3D id='i1671'\>  
> > > \<Location\>  
> > > \<IfcCartesianPoint xsi:nil='true' ref='i1667'/\>  
> > > \</Location\>  
> > > \</IfcAxis2Placement3D\>  
> > > --- VISIT:  
> > > \<IfcCartesianPoint id='i1667'\>  
> > > \<Coordinates exp:cType='list' id='i1670'\>  
> > > \<IfcLengthMeasure exp:pos='0'\>117.4\</IfcLengthMeasure\>  
> > > \<IfcLengthMeasure exp:pos='1'\>119.7\</IfcLengthMeasure\>  
> > > \<IfcLengthMeasure exp:pos='2'\>0.\</IfcLengthMeasure\>  
> > > \</Coordinates\>  
> > > \</IfcCartesianPoint\>  
> > > 10:11:43 Temp$ cat -n rx.rb  
> > > 1 #!/bin/env ruby19  
> > > 2  
> > > 3 require 'rexml/document'  
> > > 4  
> > > 5 doc = REXML::Document.new(DATA.read)  
> > > 6  
> > > 7 # BFS  
> > > 8 queue = %w{i1671}  
> > > 9  
> > > 10 until queue.empty?  
> > > 11 id = queue.shift  
> > > 12  
> > > 13 REXML::XPath.each(doc, "//\*[@id='#{id}']") do |e|  
> > > 14 puts "--- VISIT:", e  
> > > 15  
> > > 16 REXML::XPath.each(e, './/\*[@ref]') do |child|  
> > > 17 next\_id = child.attribute('ref') and queue.push(next\_id)  
> > > 18 end  
> > > 19 end  
> > > 20 end  
> > > 21  
> > > 22 \_\_END\_\_  
> > > 23 \<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
> > > 24 \<IfcWallStandardCase id="i1677"\>  
> > > 25 \<ObjectPlacement\>  
> > > 26 \<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
> > > 27 \</ObjectPlacement\>  
> > > 28 \</IfcWallStandardCase\>  
> > > 29  
> > > 30 \<IfcAxis2Placement3D id="i1671"\>  
> > > 31 \<Location\>  
> > > 32 \<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
> > > 33 \</Location\>  
> > > 34 \</IfcAxis2Placement3D\>  
> > > 35  
> > > 36 \<IfcCartesianPoint id="i1667"\>  
> > > 37 \<Coordinates id="i1670" exp:cType="list"\>  
> > > 38 \<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
> > > 39 \<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
> > > 40 \<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
> > > 41 \</Coordinates\>  
> > > 42 \</IfcCartesianPoint\>  
> > > 43 \</root\>  
> > > 10:11:47 Temp$
> > 
> > I will give this a try.
> > 
> > > Kind regards
> > > 
> > > robert
> > 
> > Dear 7stud. Using the XPath command:
> > 
> > doc = Document.new xml  
> > target = XPath.match(doc, "//\*[@id = 'i1671']")  
> > p target
> > 
> > It produces the following output as you said it would.  
> > --output:--  
> > [\<IfcAxis2Placement3D id='i1671'\> ... \</\>]
> > 
> > But I cannot figure out how to do anything with this from here to get to  
> > the next point, and eventually be able to grab the three values.

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [4 April 2011 18:44 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/11 "2011-04-04T18:44:04Z")

</div>

Thank you too Robert. This is a great explanation.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [10 April 2011 23:01 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/12 "2011-04-10T23:01:11Z")

</div>

"Jesús Gabriel y Galán" \<jgabrielygalan@gmail.com\> wrote in post  
#990433:

> I usually use Nokogiri to handle XML documents, and find css selectors  
> easier than XPath. I'd do it like this:
> 
> doc = Nokogiri::XML(\<\<END  
> \<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
> \<IfcWallStandardCase id="i1677"\>  
> \<ObjectPlacement\>  
> &nbsp;&nbsp;&nbsp;\<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
> \</ObjectPlacement\>  
> \</IfcWallStandardCase\>
> 
> \<IfcAxis2Placement3D id="i1671"\>  
> \<Location\>  
> &nbsp;&nbsp;&nbsp;\<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
> \</Location\>  
> \</IfcAxis2Placement3D\>
> 
> \<IfcCartesianPoint id="i1667"\>  
> \<Coordinates id="i1670" exp:cType="list"\>  
> &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
> \</Coordinates\>  
> \</IfcCartesianPoint\>  
> \</root\>  
> END  
> )
> 
> reference = doc.css("#i1671 Location  
> IfcCartesianPoint").attribute("ref").value  
> doc.css("##{reference} Coordinates IfcLengthMeasure").map {|element|  
> element.text}
> 
> This returns: =\> ["117.4", "119.7", "0."]

Thank you for the help. I had been using REXML and it was working find  
with one exception, it can be very slow. So now I am trying to use  
Nokogiri, and am running into a very simple error, I cannot load xml  
files. From the Nokogiri website I have been trying what is in their  
tutorial:  
f = File.open("blossom.xml")  
doc = Nokogiri::XML(f)  
f.close

But regardles of what I put in the ("...") it returns -  
Error: #\<Errno::EINVAL: C:/Program Files (x86)/Google/Google SketchUp  
8/Plugins/examples/auto.rb:11:in `read': Invalid argument -  
c:ourwalls.xml\>  
or  
Error: #\<Errno::ENOENT: C:/Program Files (x86)/Google/Google SketchUp  
8/Plugins/examples/auto.rb:11:in `read': No such file or directory -  
fourwalls.xml\>

If I am simply trying to open an XML file named file.xml located at C:\,  
what would I put to open it? I have tried many things such as f  
=File.open("C:\file.xml") and what not with no luck. What do I need to  
do to open this?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [10 April 2011 23:27 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/13 "2011-04-10T23:27:45Z")

</div>

Kyle X. wrote in post #992033:

> "Jesús Gabriel y Galán" \<jgabrielygalan@gmail.com\> wrote in post  
> #990433:
> 
> > I usually use Nokogiri to handle XML documents, and find css selectors  
> > easier than XPath. I'd do it like this:
> > 
> > doc = Nokogiri::XML(\<\<END  
> > \<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
> > \<IfcWallStandardCase id="i1677"\>  
> > \<ObjectPlacement\>  
> > &nbsp;&nbsp;&nbsp;\<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
> > \</ObjectPlacement\>  
> > \</IfcWallStandardCase\>
> > 
> > \<IfcAxis2Placement3D id="i1671"\>  
> > \<Location\>  
> > &nbsp;&nbsp;&nbsp;\<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
> > \</Location\>  
> > \</IfcAxis2Placement3D\>
> > 
> > \<IfcCartesianPoint id="i1667"\>  
> > \<Coordinates id="i1670" exp:cType="list"\>  
> > &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
> > &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
> > &nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
> > \</Coordinates\>  
> > \</IfcCartesianPoint\>  
> > \</root\>  
> > END  
> > )
> > 
> > reference = doc.css("#i1671 Location  
> > IfcCartesianPoint").attribute("ref").value  
> > doc.css("##{reference} Coordinates IfcLengthMeasure").map {|element|  
> > element.text}
> > 
> > This returns: =\> ["117.4", "119.7", "0."]

Please disregard the previous post. I figured out how to load the  
files, but it does not appear to be reading correctly.

Using-  
fname = File.open("C:/Users/Kyle/Desktop/CSUF/Research Winter  
11/IFXCML/automation trials/one.xml")  
$doc = Nokogiri::XML(fname)  
reference = $doc.css(" IfcCartesianPoint Coordinates  
IfcLengthMeasure").first

This produce and output of nil when it should be "117.4" correct? What  
is going wrong here?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Jesus\_Gabriel\_y\_Gala](https://avatars.discourse-cdn.com/v4/letter/j/96bed5/32.png) [@Jesus\_Gabriel\_y\_Gala](https://rubytalk.org/u/Jesus_Gabriel_y_Gala)\
**Post date:** [11 April 2011 07:37 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/14 "2011-04-11T07:37:41Z")

</div>

This works for me:

$ cat noko.rb && ruby -rubygems noko.rb  
require 'nokogiri'

doc = Nokogiri::XML(File.read("one.xml"))  
reference = doc.css("IfcCartesianPoint Coordinates IfcLengthMeasure").first  
puts reference.text

117.4

But if I leave a space before IfcCartesianPoint in the call to the css  
method I get a parser error (`on\_error': unexpected ' ' after ''  
(Nokogiri::CSS::SyntaxError)). This is my file one.xml:

\<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
&nbsp;&nbsp;\<IfcWallStandardCase id="i1677"\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<ObjectPlacement\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</ObjectPlacement\>  
&nbsp;&nbsp;\</IfcWallStandardCase\>

&nbsp;&nbsp;\<IfcAxis2Placement3D id="i1671"\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<Location\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
&nbsp;&nbsp;&nbsp;&nbsp;\</Location\>  
&nbsp;&nbsp;\</IfcAxis2Placement3D\>

&nbsp;&nbsp;\<IfcCartesianPoint id="i1667"\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<Coordinates id="i1670" exp:cType="list"\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</Coordinates\>  
&nbsp;&nbsp;\</IfcCartesianPoint\>  
\</root\>

This works too:

doc.css("IfcCartesianPoint Coordinates IfcLengthMeasure").each {|el|  
puts el.text}

Produces:

117.4  
119.7  
0.

Maybe it's the way you are passing the file to Nokogiri::XML? By the  
way, in your way you are not closing the file handler. If you want to  
pass Nokogiri the file instead of reading it yourself you can do:

doc = nil  
File.open("one.xml") {|f| doc = Nokogiri::XML(f)}

or

doc = File.open("one.xml") {|f| Nokogiri::XML(f)}

This way, the file is properly closed.

Jesus.

> **···**
>
> On Mon, Apr 11, 2011 at 1:27 AM, Kyle X. \<haebooty@yahoo.com\> wrote:
> 
> > Kyle X. wrote in post #992033:
> > 
> > > "Jesús Gabriel y Galán" \<jgabrielygalan@gmail.com\> wrote in post  
> > > #990433:
> > > 
> > > > I usually use Nokogiri to handle XML documents, and find css selectors  
> > > > easier than XPath. I'd do it like this:
> > > > 
> > > > doc = Nokogiri::XML(\<\<END  
> > > > \<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
> > > > \<IfcWallStandardCase id="i1677"\>  
> > > > \<ObjectPlacement\>  
> > > > \<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
> > > > \</ObjectPlacement\>  
> > > > \</IfcWallStandardCase\>
> > > > 
> > > > \<IfcAxis2Placement3D id="i1671"\>  
> > > > \<Location\>  
> > > > \<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
> > > > \</Location\>  
> > > > \</IfcAxis2Placement3D\>
> > > > 
> > > > \<IfcCartesianPoint id="i1667"\>  
> > > > \<Coordinates id="i1670" exp:cType="list"\>  
> > > > \<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
> > > > \<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
> > > > \<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
> > > > \</Coordinates\>  
> > > > \</IfcCartesianPoint\>  
> > > > \</root\>  
> > > > END  
> > > > )
> > > > 
> > > > reference = doc.css("#i1671 Location  
> > > > IfcCartesianPoint").attribute("ref").value  
> > > > doc.css("##{reference} Coordinates IfcLengthMeasure").map {|element|  
> > > > element.text}
> > > > 
> > > > This returns: =\> ["117.4", "119.7", "0."]
> > 
> > Please disregard the previous post. I figured out how to load the  
> > files, but it does not appear to be reading correctly.
> > 
> > Using-  
> > fname = File.open("C:/Users/Kyle/Desktop/CSUF/Research Winter  
> > 11/IFXCML/automation trials/one.xml")  
> > $doc = Nokogiri::XML(fname)  
> > reference = $doc.css(" IfcCartesianPoint Coordinates  
> > IfcLengthMeasure").first
> > 
> > This produce and output of nil when it should be "117.4" correct? What  
> > is going wrong here?

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [11 April 2011 18:57 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/15 "2011-04-11T18:57:42Z")

</div>

> This works for me:
> 
> $ cat noko.rb && ruby -rubygems noko.rb  
> require 'nokogiri'
> 
> doc = Nokogiri::XML(File.read("one.xml"))  
> reference = doc.css("IfcCartesianPoint Coordinates  
> IfcLengthMeasure").first  
> puts reference.text
> 
> 117.4
> 
> But if I leave a space before IfcCartesianPoint in the call to the css  
> method I get a parser error (`on\_error': unexpected ' ' after ''  
> (Nokogiri::CSS::SyntaxError)). This is my file one.xml:
> 
> \<root xmlns:exp="[http://foo](http://foo)" xmlns:xsi="[http://bar](http://bar)"\>  
> &nbsp;&nbsp;\<IfcWallStandardCase id="i1677"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<ObjectPlacement\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLocalPlacement xsi:nil="true" ref="i1671"/\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</ObjectPlacement\>  
> &nbsp;&nbsp;\</IfcWallStandardCase\>
> 
> &nbsp;&nbsp;\<IfcAxis2Placement3D id="i1671"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<Location\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcCartesianPoint xsi:nil="true" ref="i1667"/\>  
> &nbsp;&nbsp;&nbsp;&nbsp;\</Location\>  
> &nbsp;&nbsp;\</IfcAxis2Placement3D\>
> 
> &nbsp;&nbsp;\<IfcCartesianPoint id="i1667"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<Coordinates id="i1670" exp:cType="list"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="0"\>117.4\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="1"\>119.7\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<IfcLengthMeasure exp:pos="2"\>0.\</IfcLengthMeasure\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</Coordinates\>  
> &nbsp;&nbsp;\</IfcCartesianPoint\>  
> \</root\>
> 
> This works too:
> 
> doc.css("IfcCartesianPoint Coordinates IfcLengthMeasure").each {|el|  
> puts el.text}
> 
> Produces:
> 
> 117.4  
> 119.7  
> 0.

Thank you for your reply. When I continue to try and read the file I  
have it keeps returning nil values and thus doesn't work. But when I  
copy and paste the xml you have written over the file I am trying to  
read then it does work. I understand that the path is slightly  
different but using the xpath command-

doc.xpath("//IfcCartesianPoint/Coordinates/IfcLengthMeasure").each {|el|  
puts el.text}

It should skip ahead to the first appearance of IfcCartesianPoint, much  
the same as it works for using REXML xpath, no? As this same sting of  
IfcCartesianPoint/Coordinates/IfcLengthMeasure appears in this file.  
Based on the documentation here -

([http://nokogiri.org/tutorials/searching\_a\_xml\_html\_document.html\](http://nokogiri.org/tutorials/searching_a_xml_html_document.html%5C))

I think it should be working but it always returns nil.

I have attached the xml file I am trying to read and was wondering if  
you could see where my error is occurring. The first instance of  
IfcCartesianPoint/Coordinates/IfcLengthMeasure appears on line 225.

> Maybe it's the way you are passing the file to Nokogiri::XML? By the  
> way, in your way you are not closing the file handler. If you want to  
> pass Nokogiri the file instead of reading it yourself you can do:
> 
> doc = nil  
> File.open("one.xml") {|f| doc = Nokogiri::XML(f)}
> 
> or
> 
> doc = File.open("one.xml") {|f| Nokogiri::XML(f)}
> 
> This way, the file is properly closed.
> 
> Jesus.

Is there an advantage to using .open vs .read? The program I am writing  
has to grab lots of information from the xml, maybe 300 items, would it  
make a difference in speed to use one vs the other? Also for me to read  
a file at say c:\one.xml for it to read I have to write -  
doc = File.open("/one.xml") {|f| Nokogiri::XML(f)}  
Another form will not read including "\one.xml"

Thank you again for your time, you have been most helpful and it is  
greatly appreciated.

Attachments:  
[http://www.ruby-forum.com/attachment/6114/one.xml](http://www.ruby-forum.com/attachment/6114/one.xml)

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Jesus\_Gabriel\_y\_Gala](https://avatars.discourse-cdn.com/v4/letter/j/96bed5/32.png) [@Jesus\_Gabriel\_y\_Gala](https://rubytalk.org/u/Jesus_Gabriel_y_Gala)\
**Post date:** [12 April 2011 08:17 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/16 "2011-04-12T08:17:11Z")

</div>

> Thank you for your reply. When I continue to try and read the file I  
> have it keeps returning nil values and thus doesn't work. But when I  
> copy and paste the xml you have written over the file I am trying to  
> read then it does work.

The difference is that you have namespaces in your file. Check this URL:

[http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/](http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/)

In order to make this work, you can do something like this:

require 'nokogiri'

doc = Nokogiri::XML(File.read("one.xml"))  
doc.collect\_namespaces.each {|key,value| puts "#{key} =\> #{value}"}  
doc.css("uosNS|IfcCartesianPoint uosNS|Coordinates  
uosNS\>IfcLengthMeasure", {"uosNS" =\>  
"[http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;\](http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;%5C)}).each {|el| puts  
el.text}

(I added a line that shows all namespaces in the document). All nodes  
under the uos node inherit the namespace referenced by the url you see  
in the code, so in order to search for nodes within the uos node, you  
need to specify the namespace.

> Is there an advantage to using .open vs .read?

read reads the whole file in memory. Passing a file handler to  
nokogiri will probably make no difference, because most likely it's  
reading the full file to memory too.

> The program I am writing  
> has to grab lots of information from the xml, maybe 300 items, would it  
> make a difference in speed to use one vs the other?

The only answer to this question is to benchmark.

> Also for me to read  
> a file at say c:\one.xml for it to read I have to write -  
> doc = File.open("/one.xml") {|f| Nokogiri::XML(f)}  
> Another form will not read including "\one.xml"

I have no experience in Windows, but I think forward slashes should  
always work (no idea about the drive letter, though).

Jesus.

> **···**
>
> On Mon, Apr 11, 2011 at 8:57 PM, Kyle X. \<haebooty@yahoo.com\> wrote:

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [12 April 2011 09:46 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/17 "2011-04-12T09:46:05Z")

</div>

> > Thank you for your reply. When I continue to try and read the file I  
> > have it keeps returning nil values and thus doesn't work. But when I  
> > copy and paste the xml you have written over the file I am trying to  
> > read then it does work.
> 
> The difference is that you have namespaces in your file. Check this URL:
> 
> [http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/](http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/)
> 
> In order to make this work, you can do something like this:
> 
> require 'nokogiri'
> 
> doc = Nokogiri::XML(File.read("one.xml"))

The alternative is

doc = File.open("one.xml") {|io| Nokogiri::XML(io)}

> doc.collect\_namespaces.each {|key,value| puts "#{key} =\> #{value}"}  
> doc.css("uosNS|IfcCartesianPoint uosNS|Coordinates  
> uosNS\>IfcLengthMeasure", {"uosNS" =\>  
> "[http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;\](http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;%5C)}).each {|el| puts  
> el.text}
> 
> (I added a line that shows all namespaces in the document). All nodes  
> under the uos node inherit the namespace referenced by the url you see  
> in the code, so in order to search for nodes within the uos node, you  
> need to specify the namespace.
> 
> > Is there an advantage to using .open vs .read?
> 
> read reads the whole file in memory. Passing a file handler to  
> nokogiri will probably make no difference, because most likely it's  
> reading the full file to memory too.

I will have to read the whole file but it may make a crucial  
difference whether it does so in one go or in chunks. Large files  
might not even be readable with the File.read approach. If you pass  
the file as a single string there is no choice but if you pass the  
File instance nokogiri can decide what to do. This is more efficient.  
Note also that because of buffering small files will have just one  
(or a few) IO operations anyway.

> > The program I am writing  
> > has to grab lots of information from the xml, maybe 300 items, would it  
> > make a difference in speed to use one vs the other?
> 
> The only answer to this question is to benchmark.

I don't think the file loading influences access speed. Once the file  
is loaded into a object structure IO is over and all operations are in  
memory plus the model of the file will be the same regardless whether  
you read in one big chunk or in smaller ones.

The two approaches to loading the file do most likely have different  
performance characteristics though.

Kind regards

robert

> **···**
>
> 2011/4/12 Jesús Gabriel y Galán \<jgabrielygalan@gmail.com\>:
> 
> > On Mon, Apr 11, 2011 at 8:57 PM, Kyle X. \<haebooty@yahoo.com\> wrote:
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Kyle\_X](https://avatars.discourse-cdn.com/v4/letter/k/8491ac/32.png) [@Kyle\_X](https://rubytalk.org/u/Kyle_X)\
**Post date:** [12 April 2011 19:39 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/18 "2011-04-12T19:39:21Z")

</div>

> The difference is that you have namespaces in your file. Check this URL:
> 
> [http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/](http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/)
> 
> In order to make this work, you can do something like this:
> 
> require 'nokogiri'
> 
> doc = Nokogiri::XML(File.read("one.xml"))  
> doc.collect\_namespaces.each {|key,value| puts "#{key} =\> #{value}"}  
> doc.css("uosNS|IfcCartesianPoint uosNS|Coordinates  
> uosNS\>IfcLengthMeasure", {"uosNS" =\>  
> "[http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;\](http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;%5C)}).each {|el| puts  
> el.text}
> 
> (I added a line that shows all namespaces in the document). All nodes  
> under the uos node inherit the namespace referenced by the url you see  
> in the code, so in order to search for nodes within the uos node, you  
> need to specify the namespace.

Thank you for the response. After reading the link you provided to make  
any xml file read using Nokogiri if it has a namespace you must include  
that with each time you are trying to grab information from it correct  
(the name space is the url in xmlns="..." correct?)? Like you did here:

> doc.css("uosNS|IfcCartesianPoint uosNS|Coordinates  
> uosNS\>IfcLengthMeasure", {"uosNS" =\>  
> "[http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;\](http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;%5C)}).each {|el| puts  
> el.text}

In the link it says that, "Even though using namespaces is essential  
when searching an XML document, Nokogiri tries to help out. If there are  
namespaces declared on the root node of a document, Nokogiri will  
automatically register those for you. You will still have to use the  
prefix when searching the document, but the URL registration is done for  
you."

Making both -  
1 doc.xpath('//xmlns:tire',  
2 'xmlns' =\> '[http://alicesautosupply.example.com/&#39](http://alicesautosupply.example.com/&#39);  
3 )  
4 doc.xpath('//xmlns:tire')  
Equal.

I tried this using the .xml I posted and it does not work. Is this  
because the xmlns is not in the first line immediately following \<?xml  
version="1.0"?\>? In turn making it necessary for every inquirary to  
include {"uosNS" =\> "[http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;\](http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;%5C)}?

> I will have to read the whole file but it may make a crucial  
> difference whether it does so in one go or in chunks. Large files  
> might not even be readable with the File.read approach. If you pass  
> the file as a single string there is no choice but if you pass the  
> File instance nokogiri can decide what to do. This is more efficient.  
> Note also that because of buffering small files will have just one  
> (or a few) IO operations anyway.

I will try both and see how each performs against each other and if both  
work properly.

Thank you both for your replies. Your help with this has been  
invaluable.

Sincerely,  
Kyle

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Jesus\_Gabriel\_y\_Gala](https://avatars.discourse-cdn.com/v4/letter/j/96bed5/32.png) [@Jesus\_Gabriel\_y\_Gala](https://rubytalk.org/u/Jesus_Gabriel_y_Gala)\
**Post date:** [12 April 2011 20:37 UTC](https://rubytalk.org/t/can-you-search-in-rexml-by-attributes/62301/19 "2011-04-12T20:37:00Z")

</div>

> > The difference is that you have namespaces in your file. Check this URL:
> > 
> > [http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/](http://tenderlovemaking.com/2009/04/23/namespaces-in-xml/)
> > 
> > In order to make this work, you can do something like this:
> > 
> > require 'nokogiri'
> > 
> > doc = Nokogiri::XML(File.read("one.xml"))  
> > doc.collect\_namespaces.each {|key,value| puts "#{key} =\> #{value}"}  
> > doc.css("uosNS|IfcCartesianPoint uosNS|Coordinates  
> > uosNS\>IfcLengthMeasure", {"uosNS" =\>  
> > "[http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;\](http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;%5C)}).each {|el| puts  
> > el.text}
> > 
> > (I added a line that shows all namespaces in the document). All nodes  
> > under the uos node inherit the namespace referenced by the url you see  
> > in the code, so in order to search for nodes within the uos node, you  
> > need to specify the namespace.
> 
> Thank you for the response. After reading the link you provided to make  
> any xml file read using Nokogiri if it has a namespace you must include  
> that with each time you are trying to grab information from it correct  
> (the name space is the url in xmlns="..." correct?)?

Yes.

> Like you did here:
> 
> > doc.css("uosNS|IfcCartesianPoint uosNS|Coordinates  
> > uosNS\>IfcLengthMeasure", {"uosNS" =\>  
> > "[http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;\](http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;%5C)}).each {|el| puts  
> > el.text}
> 
> In the link it says that, "Even though using namespaces is essential  
> when searching an XML document, Nokogiri tries to help out. If there are  
> namespaces declared on the root node of a document, Nokogiri will  
> automatically register those for you. You will still have to use the  
> prefix when searching the document, but the URL registration is done for  
> you."
> 
> Making both -  
> 1 doc.xpath('//xmlns:tire',  
> 2 'xmlns' =\> '[http://alicesautosupply.example.com/&#39](http://alicesautosupply.example.com/&#39);  
> 3 )  
> 4 doc.xpath('//xmlns:tire')  
> Equal.
> 
> I tried this using the .xml I posted and it does not work. Is this  
> because the xmlns is not in the first line immediately following \<?xml  
> version="1.0"?\>? In turn making it necessary for every inquirary to  
> include {"uosNS" =\> "[http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;\](http://www.iai-tech.org/ifcXML/IFC2x3/FINAL&quot;%5C)}?

Correct. The root node of your XML is the doc tag, which declares  
namespaces, but the uos tag has its own namespace too. nokogiri will  
register the ones present in the root node, as the article says. The  
children nodes of uos inherit the namespace declared in the uos tag,  
so this is what you have to use to search. I have not checked the  
behaviour about the automatic registering of namespaces, but reading  
the article this is how I understand it.

Jesus.

> **···**
>
> On Tue, Apr 12, 2011 at 9:39 PM, Kyle X. \<haebooty@yahoo.com\> wrote:
