Chris McMahon wrote:
> Hi...
>
> say I have a document
>
> <plan xsi:type="ns0:plan">
>   <id>123</id>
>   <status>ACTIVE</status>
>   <jellyBean>RED</jellyBean>
>   <foo>BAR</foo>
> </plan>
> <plan xsi:type="ns0:plan">
>   <id>456</id>
>   <status>BOGUS</status>
>   <jellyBean>BLUE</jellyBean>
>   <foo>BAZ</foo>
> </plan>
>
> 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...

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__
<plan xsi:type="ns0:plan">
  <id>123</id>
  <status>ACTIVE</status>
  <jellyBean>RED</jellyBean>
  <foo>BAR</foo>
</plan>
<plan xsi:type="ns0:plan">
  <id>456</id>
  <status>BOGUS</status>
  <jellyBean>BLUE</jellyBean>
  <foo>BAZ</foo>
</plan>