neverland
10/5/2006 9:05:00 PM
In article <1160074988.503926.101250@b28g2000cwb.googlegroups.com>,
<jeffnyman@gmail.com> wrote:
>Greetings all.
>
>When processing XML, is there a way to check what the previous and what
>the next "rows" are?
>
>That probably makes no sense without context, so here is an example. I
>need to find things in the XML based on rules. For example, one rule
>might be "find the first 203 that comes after 202." Another rule is
>"Find the first 203 that comes before 16." So say I have this:
>
><variable value="202">
><variable value="203">
><variable value="203">
><variable value="203">
><variable value="203">
><variable value="203">
><variable value="16">
>
>I have to be able to find that the element after 202 is 203. (As
>opposed to a situation where a 202 appeared, but the next element was
>not 203.) I then have to determine that the element after a given 203
>is 16. Then I have to change the value attribute of the first and last
>203 elements. [.....]
>
>Has anyone done something similar in their work?
>
>- Jeff
I've just been playing with a project that looks like it might have
some similarities. I acquired an app that creates an XML representation
of a midifile, and I wanted to add useful info to the XML to help the
human reader (and maybe allow other postprocessing). In particular,
a 'note' in a midifile is begun with a NoteOn event, and ends sometime
later when a corrsponding NoteOff appears. I wanted to add an attribute
to each NoteOn element that gave its actual duration. Other elements
that had added attributes could (otherwise) be output again immediately,
but the NoteOns would have to be held until the NoteOff was read, and
as order is important that meant other events might have to wait, too.
(Of course I'm using stream parsing here. the XML-ized midifile can
get pretty long, and I don't like the idea of keeping an entire DOM
tree around. I'm kind of more at home with streams, anyway.)
Essentially I make a list of the elements waiting to be output. Each
object in the list has a 'complete' flag that is set immediately for
most tags, except for NoteOn, which is set complete when the NoteOff
arrives and the duration can be calculated. When the first element
in the list becomes complete, all finished items at the head of the list
are output.
To keep track of the reading end of things I have Element Handler
objects that can maintain knowledge of the current state (which in the
case of NoteOn/Offs means a fairly large array of references, but for
your purposes would just be the value of the previous 'variable').
I actually wrote an extension to REXML for this that I think is quite
useful, and will publish -- soon, I hope. I don't think that would
be needed for your job, though; a simple 'tag_start' handler (from
REXML::StreamListener) that recognized tag 'variable' should be
adequate.
You'd then just have to note, when you got a '203' whether the
previous was '202' and modify it if so. If not, you'd hold on to
it until the next 'variable'; if that was '16', you'd modify it
and output it, otherwise you'd just output it. You wouldn't even
need a list if there were never any intervening elements.
Oof! Sorry, that got rather long-winded, and I don't know if it made
any sense, but I hope it's useful.
-- Pete --
--
============================================================================
The address in the header is a Spam Bucket -- don't bother replying to it...
(If you do need to email, replace the account name with my true name.)