# Construct AoA with REXML XPath?

**URL:** <https://www.ruby-forum.com/t/construct-aoa-with-rexml-xpath/54977>\
**Category:** Ruby\
**Created:** [March 15, 2006, 8:06pm UTC](https://www.ruby-forum.com/t/construct-aoa-with-rexml-xpath/54977 "2006-03-15T20:06:31Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chris\_McMahon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/74df32/32.png) [@Chris\_McMahon](https://www.ruby-forum.com/u/Chris_McMahon)\
**Post date:** [March 15, 2006, 8:06pm UTC](https://www.ruby-forum.com/t/construct-aoa-with-rexml-xpath/54977/1 "2006-03-15T20:06:31Z")

</div>

Hi…

say I have a document

 123 ACTIVE RED BAR 456 BOGUS BLUE BAZ

I know I can do  
ids = doc.elements.to\_a( “//plan/id”)  
jellybeans = doc.elements.to\_a( “//plan/jellyBean”)

but is there some way to do something like

idsAndJellyBeans = doc.elements.to\_a( “//plan/id” “//plan/jellyBean”)

and get

[[123, “RED”],[456,“BLUE”]]?

Thanks…

---

<div class="post-metadata">

**Author:** ![Chris\_McMahon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/74df32/32.png) [@Chris\_McMahon](https://www.ruby-forum.com/u/Chris_McMahon)\
**Post date:** [March 15, 2006, 10:47pm UTC](https://www.ruby-forum.com/t/construct-aoa-with-rexml-xpath/54977/2 "2006-03-15T22:47:15Z")

</div>

You could use Array#zip

ids = doc.elements.to\_a( “//plan/id/”).map{|i| i.text}  
=\> [“123”, “456”]

jellybeans = doc.elements.to\_a( “//plan/jellyBean”).map {|i| i.text}  
=\> [“RED”, “BLUE”]

idsAndJellyBeans = ids.zip(jellybeans)  
=\> [[“123”, “RED”], [“456”, “BLUE”]]

---

<div class="post-metadata">

**Author:** ![Chris\_McMahon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/74df32/32.png) [@Chris\_McMahon](https://www.ruby-forum.com/u/Chris_McMahon)\
**Post date:** [March 15, 2006, 11:24pm UTC](https://www.ruby-forum.com/t/construct-aoa-with-rexml-xpath/54977/3 "2006-03-15T23:24:23Z")

</div>

Yes, but I wonder if there is a rock-solid guarantee that each array  
that is an element of idsAndJellyBeans is in fact from the same “plan”  
record.

Empirical research suggests that they are, but I’m nervous. That’s why  
I wonder if there is some sort of pure-REXML trick that would extract  
multiple elements from within a single record, so that I could always  
be sure that the id and the jellyBean in each individual array had FER  
SHURE come from the same “plan” record.

---

<div class="post-metadata">

**Author:** ![Chris\_McMahon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/74df32/32.png) [@Chris\_McMahon](https://www.ruby-forum.com/u/Chris_McMahon)\
**Post date:** [March 16, 2006, 5:56am UTC](https://www.ruby-forum.com/t/construct-aoa-with-rexml-xpath/54977/4 "2006-03-16T05:56:47Z")

</div>

Chris McMahon wrote:

> but is there some way to do something like
> 
> idsAndJellyBeans = doc.elements.to\_a( “//plan/id” “//plan/jellyBean”)
> 
> and get
> 
> [[123, “RED”],[456,“BLUE”]]?
> 
> Thanks…

Using plain Ruby:

class Array; alias atr first; alias txt last end  
class String  
def xtag(str)  
result = []  
re = %r{ \< #{str} (?: \s+ ( (?\> [^\>"/]\* (?\> “[^”]_" )? )_ ) )? }xi  
scan( %r{ #{re} / \> | #{re} \> ( ._? ) \</ #{str} \>  
}mix )   
{ |unpaired, attr, data| h = { }  
( unpaired || attr || “” ).  
scan( %r{ ( \w+ ) \s_ = \s\* (?: " ( [^"]\* ) " | ( \S+ ) )  
}mx ) { |k,v,v2|  
h[k.downcase] = (v || v2) }  
block\_given? ? ( yield [h, data] ) : result \<\< [h, data]  
}  
result  
end  
end

p DATA.read.xtag(‘plan’).map{|attr,text|  
[ text.xtag(‘id’).first.txt,  
text.xtag(‘jellyBean’).first.txt  
]  
}

**END**  
  
123  
ACTIVE  
RED  
BAR  
  
  
456  
BOGUS  
BLUE  
BAZ
