
At Sun, 20 May 2007 10:55:26 +0100, Malcolm Wallace wrote:
"Jeremy Shaw"
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>
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.