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…
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”]]
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.
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