{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies,
FlexibleContexts #-}-- | A variant of /Node/ in which Element nodes have an annotation of any type,-- and some concrete functions that annotate with the XML parse location.---- The names conflict with those in /Tree/ so you must use qualified import-- if you want to use both modules.moduleText.XML.Expat.Annotated(-- * Tree structureNode,NodeG(..),UNode,LNode,ULNode,-- * Generic node manipulationmoduleText.XML.Expat.NodeClass,-- * Annotation-specificunannotate,modifyAnnotation,mapAnnotation,-- * Qualified nodesQName(..),QNode,QAttributes,QLNode,toQualified,fromQualified,-- * Namespaced nodesNName(..),NNode,NAttributes,NLNode,mkNName,mkAnNName,toNamespaced,fromNamespaced,xmlnsUri,xmlns,-- * Parse to treeTree.ParserOptions(..),Tree.defaultParserOptions,Encoding(..),parse,parse',XMLParseError(..),XMLParseLocation(..),-- * Variant that throws exceptionsparseThrowing,XMLParseException(..),-- * SAX-style parseSAXEvent(..),saxToTree,-- * Abstraction of string typesGenericXMLString(..),-- * DeprecatedeAttrs,parseSAX,parseSAXThrowing,parseSAXLocations,parseSAXLocationsThrowing,parseTree,parseTree',parseTreeThrowing)whereimportControl.ArrowimportqualifiedText.XML.Expat.TreeasTreeimportText.XML.Expat.SAX(Encoding(..),GenericXMLString(..),ParserOptions(..),SAXEvent(..),XMLParseError(..),XMLParseException(..),XMLParseLocation(..),parseSAX,parseSAXThrowing,parseSAXLocations,parseSAXLocationsThrowing)importqualifiedText.XML.Expat.SAXasSAXimportText.XML.Expat.Qualifiedhiding(QNode,QNodes)importText.XML.Expat.Namespacedhiding(NNode,NNodes)importText.XML.Expat.NodeClassimportControl.Monad(mplus,mzero)importControl.Parallel.StrategiesimportqualifiedData.ByteStringasBimportqualifiedData.ByteString.LazyasLimportData.List.ClassimportData.Monoid-- | Annotated variant of the tree representation of the XML document, meaning-- that it has an extra piece of information of your choice attached to each-- Element.---- @c@ is the container type for the element's children, which is usually [],-- except when you are using chunked I\/O with the @hexpat-iteratee@ package.---- @tag@ is the tag type, which can either be one of several string types,-- or a special type from the @Text.XML.Expat.Namespaced@ or-- @Text.XML.Expat.Qualified@ modules.---- @text@ is the string type for text content.---- @a@ is the type of the annotation. One of the things this can be used for-- is to store the XML parse location, which is useful for error handling.---- Note that some functions in the @Text.XML.Expat.Cursor@ module need to create-- new nodes through the 'MkElementClass' type class. Normally this can only be done-- if @a@ is a Maybe type (so it can provide the Nothing value for the annotation-- on newly created nodes). Or, you can write your own 'MkElementClass' instance.-- Apart from that, there is no requirement for @a@ to be a Maybe type.dataNodeGactagtext=Element{eName::!tag,eAttributes::![(tag,text)],eChildren::c(NodeGactagtext),eAnn::a}|Text!text-- | A pure tree representation that uses a list as its container type,-- annotated variant.typeNodea=NodeGa[]instance(Showtag,Showtext,Showa)=>Show(NodeGa[]tagtext)whereshow(Elementnaatchan)="Element "++showna++" "++showat++" "++showch++" "++showanshow(Textt)="Text "++showtinstance(Eqtag,Eqtext,Eqa)=>Eq(NodeGa[]tagtext)whereElementna1at1ch1an1==Elementna2at2ch2an2=na1==na2&&at1==at2&&ch1==ch2&&an1==an2Textt1==Textt2=t1==t2_==_=FalseeAttrs::Nodeatagtext->[(tag,text)]{-# DEPRECATED eAttrs "use eAttributes instead" #-}eAttrs=eAttributesinstance(NFDatatag,NFDatatext,NFDataa)=>NFData(NodeGa[]tagtext)wherernf(Elementnamattchiann)=rnf(nam,att,chi,ann)rnf(Texttxt)=rnftxtinstance(Functorc,Listc)=>NodeClass(NodeGa)cwheretextContentM(Element__children_)=foldlLmappendmempty$joinM$fmaptextContentMchildrentextContentM(Texttxt)=returntxtisElement(Element____)=TrueisElement_=FalseisText(Text_)=TrueisText_=FalseisNamed_(Text_)=FalseisNamednm(Elementnm'___)=nm==nm'getName(Text_)=memptygetName(Elementname___)=namegetAttributes(Text_)=[]getAttributes(Element_attrs__)=attrsgetChildren(Text_)=mzerogetChildren(Element__ch_)=chgetText(Texttxt)=txtgetText(Element____)=memptymodifyName_node@(Text_)=nodemodifyNamef(Elementnacann)=Element(fn)acannmodifyAttributes_node@(Text_)=nodemodifyAttributesf(Elementnacann)=Elementn(fa)cannmodifyChildren_node@(Text_)=nodemodifyChildrenf(Elementnacann)=Elementna(fc)annmapAllTags_(Textt)=TexttmapAllTagsf(Elementnacann)=Element(fn)(map(firstf)a)(fmap(mapAllTagsf)c)annmapElement_(Textt)=TexttmapElementf(Elementnacann)=let(n',a',c')=f(n,a,c)inElementn'a'c'annmapNodeContainerf(Elementnachan)=doch'<-fchreturn$Elementnach'anmapNodeContainer_(Textt)=return$TexttmkText=Textinstance(Functorc,Listc)=>MkElementClass(NodeG(Maybea))cwheremkElementnameattrschildren=ElementnameattrschildrenNothing-- | Convert an annotated tree (/Annotated/ module) into a non-annotated-- tree (/Tree/ module). Needed, for example, when you @format@ your tree to-- XML, since @format@ takes a non-annotated tree.unannotate::Functorc=>NodeGactagtext->Tree.NodeGctagtextunannotate(Elementnaatch_)=(Tree.Elementnaat(fmapunannotatech))unannotate(Textt)=Tree.Textt-- | Type shortcut for a single annotated node with unqualified tag names where-- tag and text are the same string typetypeUNodeatext=Nodeatexttext-- | Type shortcut for a single annotated node, annotated with parse locationtypeLNodetagtext=NodeXMLParseLocationtagtext-- | Type shortcut for a single node with unqualified tag names where-- tag and text are the same string type, annotated with parse locationtypeULNodetext=LNodetexttext-- | Type shortcut for a single annotated node where qualified names are used for tagstypeQNodeatext=Nodea(QNametext)text-- | Type shortcut for a single node where qualified names are used for tags, annotated with parse locationtypeQLNodetext=LNode(QNametext)text-- | Type shortcut for a single annotated node where namespaced names are used for tagstypeNNodetexta=Nodea(NNametext)text-- | Type shortcut for a single node where namespaced names are used for tags, annotated with parse locationtypeNLNodetext=LNode(NNametext)text-- | Modify this node's annotation (non-recursively) if it's an element, otherwise no-op.modifyAnnotation::(a->a)->Nodeatagtext->Nodeatagtextf`modifyAnnotation`Elementnaatchan=Elementnaatch(fan)_`modifyAnnotation`Textt=Textt-- | Modify this node's annotation and all its children recursively if it's an element, otherwise no-op.mapAnnotation::(a->b)->Nodeatagtext->Nodebtagtextf`mapAnnotation`Elementnaatchan=Elementnaat(map(f`mapAnnotation`)ch)(fan)_`mapAnnotation`Textt=Textt-- | A lower level function that lazily converts a SAX stream into a tree structure.-- Variant that takes annotations for start tags.saxToTree::GenericXMLStringtag=>[(SAXEventtagtext,a)]->(Nodeatagtext,MaybeXMLParseError)saxToTreeevents=let(nodes,mError,_)=ptleventsin(safeHeadnodes,mError)wheresafeHead(a:_)=asafeHead[]=Element(gxFromString"")[][](error"saxToTree null annotation")ptl((StartElementnameattrs,ann):rema)=let(children,err1,rema')=ptlremaelt=Elementnameattrschildrenann(out,err2,rema'')=ptlrema'in(elt:out,err1`mplus`err2,rema'')ptl((EndElement_,_):rema)=([],Nothing,rema)ptl((CharacterDatatxt,_):rema)=let(out,err,rema')=ptlremain(Texttxt:out,err,rema')ptl((FailDocumenterr,_):_)=([],Justerr,[])ptl[]=([],Nothing,[])-- | Lazily parse XML to tree. Note that forcing the XMLParseError return value-- will force the entire parse. Therefore, to ensure lazy operation, don't-- check the error status until you have processed the tree.parse::(GenericXMLStringtag,GenericXMLStringtext)=>ParserOptionstagtext-- ^ Optional encoding override->L.ByteString-- ^ Input text (a lazy ByteString)->(LNodetagtext,MaybeXMLParseError)parseoptsbs=saxToTree$SAX.parseLocationsoptsbs-- | DEPRECATED: Use 'parse' instead.---- Lazily parse XML to tree. Note that forcing the XMLParseError return value-- will force the entire parse. Therefore, to ensure lazy operation, don't-- check the error status until you have processed the tree.parseTree::(GenericXMLStringtag,GenericXMLStringtext)=>MaybeEncoding-- ^ Optional encoding override->L.ByteString-- ^ Input text (a lazy ByteString)->(LNodetagtext,MaybeXMLParseError){-# DEPRECATED parseTree "use Text.XML.Annotated.parse instead" #-}parseTreemEnc=parse(ParserOptionsmEncNothing)-- | Lazily parse XML to tree. In the event of an error, throw 'XMLParseException'.---- @parseThrowing@ can throw an exception from pure code, which is generally a bad-- way to handle errors, because Haskell\'s lazy evaluation means it\'s hard to-- predict where it will be thrown from. However, it may be acceptable in-- situations where it's not expected during normal operation, depending on the-- design of your program.parseThrowing::(GenericXMLStringtag,GenericXMLStringtext)=>ParserOptionstagtext-- ^ Optional encoding override->L.ByteString-- ^ Input text (a lazy ByteString)->LNodetagtextparseThrowingoptsbs=fst$saxToTree$SAX.parseLocationsThrowingoptsbs-- | DEPRECATED: use 'parseThrowing' instead---- Lazily parse XML to tree. In the event of an error, throw 'XMLParseException'.parseTreeThrowing::(GenericXMLStringtag,GenericXMLStringtext)=>MaybeEncoding-- ^ Optional encoding override->L.ByteString-- ^ Input text (a lazy ByteString)->LNodetagtext{-# DEPRECATED parseTreeThrowing "use Text.XML.Annotated.parseThrowing instead" #-}parseTreeThrowingmEnc=parseThrowing(ParserOptionsmEncNothing)-- | Strictly parse XML to tree. Returns error message or valid parsed tree.parse'::(GenericXMLStringtag,GenericXMLStringtext)=>ParserOptionstagtext-- ^ Optional encoding override->B.ByteString-- ^ Input text (a strict ByteString)->EitherXMLParseError(LNodetagtext)parse'optsbs=caseparseopts(L.fromChunks[bs])of(_,Justerr)->Lefterr(root,Nothing)->Rightroot-- | DEPRECATED: use 'parse' instead.---- Strictly parse XML to tree. Returns error message or valid parsed tree.parseTree'::(GenericXMLStringtag,GenericXMLStringtext)=>MaybeEncoding-- ^ Optional encoding override->B.ByteString-- ^ Input text (a strict ByteString)->EitherXMLParseError(LNodetagtext){-# DEPRECATED parseTree' "use Text.XML.Expat.parse' instead" #-}parseTree'mEnc=parse'(ParserOptionsmEncNothing)