construct AoA with REXML XPath?

C

Chris McMahon

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...
 
G

Gordon Thiesfeld

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"]]
 
C

Chris McMahon

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.
 
W

William James

Chris said:
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>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,044
Latest member
RonaldNen

Latest Threads

Top