At Sun, 20 May 2007 10:55:26 +0100, Malcolm Wallace wrote: > > "Jeremy Shaw" <[EMAIL PROTECTED]> writes: > > > How do I create a HaXml filter that adds a new element as a child of > > an existing element. For example, let's say I have the XML document: > > <a> <b/> <c/> </a> > > How do I add a new element under <a /> so that I have the document: > > <a> <newElement/> <b/> <c/> </a> > > Using the combinators, it goes something like this: > > mkElem "a" [ mkElem "newElement" [] > , children ] `o` tag "a" > > Having matched the outer tag, you then rebuild it with some extra stuff > added. Obviously you would abstract the common pattern if you do this > frequently: > > insertAtStart :: String -> String -> CFilter > insertAtStart outer newelem = > mkElem outer [ mkElem newElem [] > , children ] `o` tag outer
Thanks! I should probably mention that I don't actually have a specific problem I am trying to solve here. I am trying to write a tutorial on how to use the combinators, and there is a certain class of problems I can't seem to handle. I am not sure if it is because there is a hole in my understanding, or if there is an hole in what the combinators can express. The hole is related to operations that want to edit the children of a element in some sort of aggregate manner. The current example is inserting a new element. Another example is sorting the children. Going back to the example at hand, what if I don't know the name and attributes of the parent? For example, if I have the document: <top> <section attr="value1"> <b /> <b /> </section> <section2 attr="value3"> <b /> </section2> <othersection attr=\"value2\"/> </top> And a I want to add single <newElement /> to any child of <top> that already has one or more <b /> element, so I get this output: <top> <section attr="value1"> <newElement /> <b /> <b /> </section> <section2 attr="value3"> <newElement /> <b /> </section2> <othersection attr="value2"/> </top> A solution that comes close is this filter: > chip ((chip (mkElem "newElement" [] `union` keep)) `when` (elm /> tag "b")) Except that it will produce a <newElement /> for *every* <b />, whereas I only want a single <newElement /> per parent. If I introduce a new (poorly named) primitive: > editElem :: CFilter -> CFilter > editElem f c@(CElem (Elem name as _)) = [ CElem (Elem name as (f c)) ] Then I can express the filter like this: > chip (editElem (mkElem "newElement" [] `union` children) `when` (keep /> tag > "b")) But, I don't see an obvious way to implement 'editElem' using the existing combinators. On the other hand, 'chip' can be implemented in terms of 'editElem': > chip' = editElem children but, I am not sure what implications that has, if any. thanks! j. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe