-- |-- Navigable tree structure which allow a program to traverse-- for XPath expressions-- copied and modified from HXML (<http://www.flightlab.com/~joe/hxml/>)--moduleText.XML.HXT.XPath.NavTree(moduleText.XML.HXT.XPath.NavTree,moduleData.Tree.NTree.TypeDefs)whereimportData.MaybeimportData.Tree.NTree.TypeDefsimportText.XML.HXT.DOM.Interface(XNode,xmlnsNamespace,namespaceUri)importText.XML.HXT.DOM.XmlNode(isRoot,isElem,getName,getAttrl)-- ------------------------------------------------------------------------------- NavTree---- | navigable tree with nodes of type node---- a navigable tree consists of a n-ary tree for the current fragment tree,-- a navigable tree for all ancestors, and two n-ary trees for-- the previous- and following siblingsdataNavTreea=NT{self::(NTreea),selfIndex::Int,ancestors::[NavTreea],previousSiblings::[NTreea],followingSiblings::[NTreea]}deriving(Show)-- deriving not reasonable for Eq and Ord-- ------------------------------------------------------------------------------- |-- converts a n-ary tree in a navigable treentree::NTreea->NavTreeantreend=NTnd(-1)[][][]-- |-- converts a navigable tree in a n-ary treesubtreeNT::NavTreea->NTreeasubtreeNT(NTnd____)=nd-- |-- function for selecting the value of the current fragment treedataNT::NavTreea->adataNT(NT(NTreea_)____)=a-- |-- function for selecting all children of a treechildrenNT::NavTreea->[NTreea]childrenNT(NT(NTree_cs)____)=cs-- |-- position of tree in parentindexNT::NavTreea->IntindexNT(NT_ix___)=ix-- |-- path (index list) of a navigatable treepathNT::NavTreea->[Int]pathNT=tail.reverse.mapselfIndex.ancestorOrSelfAxis-- ------------------------------------------------------------------------------- functions for traversing up, down, left and right in a navigable treeupNT,downNT,leftNT,rightNT::NavTreea->Maybe(NavTreea)upNT(NT__(p:_)__)=JustpupNT(NT__[]__)=NothingdownNTt@(NT(NTree_(c:cs))_u__)=Just(NTc0(t:u)[]cs)downNT(NT(NTree_[])____)=NothingleftNT(NTsixu(l:ls)r)=Just(NTl(ix-1)uls(s:r))leftNT(NT___[]_)=NothingrightNT(NTsixul(r:rs))=Just(NTr(ix+1)u(s:l)rs)rightNT(NT____[])=Nothing-- preorderNT t = t : concatMap preorderNT (children t)-- where children = maybe [] (maybeStar rightNT) . downNTpreorderNT::NavTreea->[NavTreea]preorderNT=visit[]wherevisitkt=t:maybek(visit'k)(downNTt)visit'kt=visit(maybek(visit'k)(rightNTt))trevPreorderNT::NavTreea->[NavTreea]revPreorderNTt=t:concatMaprevPreorderNT(reverse(childrent))wherechildren=maybe[](maybeStarrightNT).downNTgetChildrenNT::NavTreea->[NavTreea]getChildrenNTnode=maybe[]follow(downNTnode)wherefollown=n:maybe[]follow(rightNTn)-- ------------------------------------------------------------------------------- Miscellaneous useful combinators-- |-- Kleisli composition:o'::(b->[c])->(a->[b])->(a->[c])f`o'`g=\x->gx>>=f-- Some useful anamorphisms:maybeStar,maybePlus::(a->Maybea)->a->[a]maybeStarfa=a:maybe[](maybeStarf)(fa)maybePlusfa=maybe[](maybeStarf)(fa)-- ------------------------------------------------------------------------------- functions for representing XPath axes. All axes except the namespace-axis are supportedparentAxis::NavTreea->[NavTreea]parentAxis=maybeToList.upNTancestorAxis::NavTreea->[NavTreea]ancestorAxis=ancestors-- or: maybePlus upNTancestorOrSelfAxis::NavTreea->[NavTreea]ancestorOrSelfAxist=t:ancestorst-- or: maybeStar upNTchildAxis::NavTreea->[NavTreea]childAxis=maybe[](maybeStarrightNT).downNTdescendantAxis::NavTreea->[NavTreea]descendantAxis=tail.preorderNT-- concatMap preorderNT . childAxisdescendantOrSelfAxis::NavTreea->[NavTreea]descendantOrSelfAxis=preorderNTfollowingSiblingAxis::NavTreea->[NavTreea]followingSiblingAxis=maybePlusrightNTprecedingSiblingAxis::NavTreea->[NavTreea]precedingSiblingAxis=maybePlusleftNTselfAxis::NavTreea->[NavTreea]selfAxis=(:[])followingAxis::NavTreea->[NavTreea]followingAxis=preorderNT`o'`followingSiblingAxis`o'`ancestorOrSelfAxisprecedingAxis::NavTreea->[NavTreea]precedingAxis=revPreorderNT`o'`precedingSiblingAxis`o'`ancestorOrSelfAxisattributeAxis::NavTreeXNode->[NavTreeXNode]attributeAxist@(NTxt_a__)|isElemxt&&not(isRootxt)=foldr(\(ix,attr)->((NTattrix(t:a)[][]):))[]al|otherwise=[]whereaixxs=zip[(0-lengthxs)..(-1)]xsal=filter((/=xmlnsNamespace).maybe""namespaceUri.getName.snd).aix.fromMaybe[].getAttrl$xt-- attributes are indexed in the path with negative indices-- this corresponds to document order and makes the index paths-- for attributes and children disjoint.-- The attribute index is never referenced when navigating in trees-- ------------------------------------------------------------