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. =A0Do you want to look for all
>> "ref" instances and find elements they are referring to? =A0Or 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. =A0I am sorry if what I wrote was unclear=
.
> What my goal is is to start at a given location (in this case-
> <IfcWallStandardCase id=3D"i1677">) and eventually grab the three
> IfcLengthMeasure text values, that are associated with this
> <IfcWallStandardCase id=3D"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=3D'i1671'>
>> =A0<Location>
>> =A0 =A0<IfcCartesianPoint xsi:nil=3D'true' ref=3D'i1667'/>
>> =A0</Location>
>> </IfcAxis2Placement3D>
>> --- VISIT:
>> <IfcCartesianPoint id=3D'i1667'>
>> =A0<Coordinates exp:cType=3D'list' id=3D'i1670'>
>> =A0 =A0<IfcLengthMeasure exp:pos=3D'0'>117.4</IfcLengthMeasure>
>> =A0 =A0<IfcLengthMeasure exp:pos=3D'1'>119.7</IfcLengthMeasure>
>> =A0 =A0<IfcLengthMeasure exp:pos=3D'2'>0.</IfcLengthMeasure>
>> =A0</Coordinates>
>> </IfcCartesianPoint>
>> 10:11:43 Temp$ cat -n rx.rb
>> =A0 =A0 =A01 =A0#!/bin/env ruby19
>> =A0 =A0 =A02
>> =A0 =A0 =A03 =A0require 'rexml/document'
>> =A0 =A0 =A04
>> =A0 =A0 =A05 =A0doc =3D REXML::Document.new(DATA.read)
>> =A0 =A0 =A06
>> =A0 =A0 =A07 =A0# BFS
>> =A0 =A0 =A08 =A0queue =3D %w{i1671}
>> =A0 =A0 =A09
>> =A0 =A0 10 =A0until queue.empty?
>> =A0 =A0 11 =A0 =A0id =3D queue.shift
>> =A0 =A0 12
>> =A0 =A0 13 =A0 =A0REXML::XPath.each(doc, "//*[@id=3D'#{id}']") do |e|
>> =A0 =A0 14 =A0 =A0 =A0puts "--- VISIT:", e
>> =A0 =A0 15
>> =A0 =A0 16 =A0 =A0 =A0REXML::XPath.each(e, './/*[@ref]') do |child|
>> =A0 =A0 17 =A0 =A0 =A0 =A0next_id =3D child.attribute('ref') and queue.p=
ush(next_id)
>> =A0 =A0 18 =A0 =A0 =A0end
>> =A0 =A0 19 =A0 =A0end
>> =A0 =A0 20 =A0end
>> =A0 =A0 21
>> =A0 =A0 22 =A0__END__
>> =A0 =A0 23 =A0<root xmlns:exp=3D"http://foo" xmlns:xsi=3D"http://bar">
>> =A0 =A0 24 =A0<IfcWallStandardCase id=3D"i1677">
>> =A0 =A0 25 =A0 <ObjectPlacement>
>> =A0 =A0 26 =A0 =A0 <IfcLocalPlacement xsi:nil=3D"true" ref=3D"i1671"/>
>> =A0 =A0 27 =A0 </ObjectPlacement>
>> =A0 =A0 28 =A0</IfcWallStandardCase>
>> =A0 =A0 29
>> =A0 =A0 30 =A0<IfcAxis2Placement3D id=3D"i1671">
>> =A0 =A0 31 =A0 <Location>
>> =A0 =A0 32 =A0 =A0 <IfcCartesianPoint xsi:nil=3D"true" ref=3D"i1667"/>
>> =A0 =A0 33 =A0 </Location>
>> =A0 =A0 34 =A0</IfcAxis2Placement3D>
>> =A0 =A0 35
>> =A0 =A0 36 =A0<IfcCartesianPoint id=3D"i1667">
>> =A0 =A0 37 =A0 <Coordinates id=3D"i1670" exp:cType=3D"list">
>> =A0 =A0 38 =A0 =A0 <IfcLengthMeasure exp:pos=3D"0">117.4</IfcLengthMeasu=
re>
>> =A0 =A0 39 =A0 =A0 <IfcLengthMeasure exp:pos=3D"1">119.7</IfcLengthMeasu=
re>
>> =A0 =A0 40 =A0 =A0 <IfcLengthMeasure exp:pos=3D"2">0.</IfcLengthMeasure>
>> =A0 =A0 41 =A0 </Coordinates>
>> =A0 =A0 42 =A0</IfcCartesianPoint>
>> =A0 =A0 43 =A0</root>
>> 10:11:47 Temp$
>
> I will give this a try.
>
>>
>> Kind regards
>>
>> robert
>
> Dear 7stud. =A0Using the XPath command:
>
> doc =3D Document.new xml
> target =3D XPath.match(doc, "//*[@id =3D 'i1671']")
> p target
>
> It produces the following output as you said it would.
> --output:--
> [<IfcAxis2Placement3D id=3D'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.

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

doc =3D Nokogiri::XML(<<END
<root xmlns:exp=3D"http://foo" xmlns:xsi=3D"http://bar">
<IfcWallStandardCase id=3D"i1677">
 <ObjectPlacement>
   <IfcLocalPlacement xsi:nil=3D"true" ref=3D"i1671"/>
 </ObjectPlacement>
</IfcWallStandardCase>

<IfcAxis2Placement3D id=3D"i1671">
 <Location>
   <IfcCartesianPoint xsi:nil=3D"true" ref=3D"i1667"/>
 </Location>
</IfcAxis2Placement3D>

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

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

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

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

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

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

Jesus.