From: neverland@... (Pete) Date: 2006-10-06T06:10:05+09:00 Subject: Re: Parse and modify an XML file with REXML In article <1160074988.503926.101250@b28g2000cwb.googlegroups.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: > > > > > > > > > >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.)