6320N/ADescription : compute xml diffs
6320N/ACopyright : (c) Christian Maeder, DFKI GmbH 2011
6320N/AMaintainer : Christian.Maeder@dfki.de
6320N/A{- for elements, whose order does not matter, use the given attribute keys to
6320N/Adetermine their equality. -}
6320N/AxmlDiff :: UnordTags -> [Step] -> Int -> [Content] -> [Content] -> [Change]
6320N/AxmlDiff m pth i old new = let
6320N/A np = addPathNumber (i + 1) pth
6320N/A in case (old, filter validContent new) of
6320N/A [Change (Add Append $ map contentToAddChange ns) pe]
6320N/A (\ (_, j) -> Change Remove $ pathToExpr $ addPathNumber (i + j) pth)
6320N/A (o : os, ns@(n : rt)) -> let
6320N/A restDiffs = xmlDiff m pth (i + 1) os
6320N/A rmO = Change Remove pe : restDiffs ns
6320N/A Elem e2 | elName e2 == en ->
6320N/A xmlElemDiff m nPath atts cs e2
6320N/A (mns, rns) = partition (matchElems en $
6320N/A Elem mn : rm -> xmlElemDiff m nPath atts cs mn
6320N/A | otherwise -> Change (Update nText) pe : restDiffs rt
6320N/AmatchElems en atts c = case c of
6320N/AxmlElemDiff :: UnordTags -> [Step] -> [Attr] -> [Content] -> Element -> [Change]
6320N/AxmlElemDiff m nPath atts cs e2 = xmlAttrDiff nPath atts (elAttribs e2)
6320N/A ++ xmlDiff m nPath 0 cs (elContent e2)
6320N/AxmlAttrDiff :: [Step] -> [Attr] -> [Attr] -> [Change]
6320N/A addAttrStep a = pathToExpr $ Step Attribute (NameTest $ qName a) [] : p
6320N/A in map (Change Remove . addAttrStep . fst) rms
6320N/A ++ map (\ (a, (_, v)) -> Change (Update v) $ addAttrStep a) inter
6320N/A ++ if null ins then [] else
6320N/A [Change (Add Append $ map (AddAttr . uncurry Attr) ins) $ pathToExpr p]
6320N/ApathToExpr :: [Step] -> Expr
6320N/ApathToExpr = PathExpr Nothing . Path True . reverse
6320N/AextendPath :: QName -> [Step] -> [Step]
6320N/AextendPath q = (Step Child (NameTest $ qName q) [] :)
6320N/A-- steps and predicates are reversed!
6320N/AaddPathNumber :: Int -> [Step] -> [Step]
6320N/A let e = PrimExpr Number $ show i
6320N/A Step a n es : rs -> Step a n (e : es) : rs
6320N/AvalidContent :: Content -> Bool
6320N/A CRef _ -> False -- we cannot handle this
6320N/AcontentToAddChange :: Content -> AddChange
6320N/AcontentToAddChange c = case c of
6320N/AmkXQName s = (unqual s) { qPrefix = Just xupdateS }
6320N/AchangeToXml :: Change -> Element
6320N/AchangeToXml (Change csel pth) = let
6320N/A sel = add_attr (mkAttr selectS $ show pth)
6320N/A . node (mkXQName appendS) $ map addsToXml as
6320N/A Remove -> sel $ node (mkXQName removeS) ()
6320N/A Update s -> sel $ node (mkXQName updateS) s
6320N/AaddsToXml :: AddChange -> Content
6320N/A . add_attr (mkNameAttr $ qName k) $ node (mkXQName attributeS) v
6320N/AmkMods :: [Change] -> Element
6320N/AmkMods = node (mkXQName "modifications") . map changeToXml