-- |-- basic XmlTree filtermoduleText.XML.HXT.DOM.XmlTreeFilter(moduleText.XML.HXT.DOM.XmlTreeFilter)whereimportText.XML.HXT.DOM.XmlTreeTypesimportText.XML.HXT.DOM.XmlTreeFunctionsimportText.XML.HXT.DOM.XmlKeywordsimportText.XML.HXT.DOM.Unicode(isXmlSpaceChar)importText.XML.HXT.DOM.Util(decimalStringToInt)importData.List(partition)infixl7+=,++=-- --------------------------------------------------------------------------------- filter predicates-- |-- test whether the root of a tree contains a document root node.isRoot::XmlFilterisRoot=isOfNode(isTagNodet_root)-- |-- test whether the root of a tree contains a tag node.---- see also: 'isNsTag'isTag::String->XmlFilterisTagtn=isOfNode(isTagNodetn)-- |-- namespace aware test whether the root of a tree contains a tag node. Parameters are the local part and namespace.-- Only usable after namespace propagation.---- see also: 'isTag'isNsTag::String->String->XmlFilterisNsTaglpns=isOfTag(\t->localPartt==lp&&namespaceUrit==ns)-- |-- test whether the root of a tree has a given local name-- see also : 'hasNamespace', 'hasPrefix', 'isTag', 'isAttr'hasLocalPart::String->XmlFilterhasLocalPartlp=isOf((==lp).localPartOf)-- |-- test whether the root of a tree has a given prefix name-- see also : 'hasNamespace', 'hasLocalPart', 'isTag', 'isAttr'hasPrefix::String->XmlFilterhasPrefixpx=isOf((==px).prefixOf)-- |-- test whether the root of a tree belongs to a given namespace-- see also : 'isTag', 'isAttr', 'hasLocalPart', 'hasPrefix'hasNamespace::String->XmlFilterhasNamespacens=isOf((==ns).namespaceOf)-- |-- test whether the root of a tree contains a tag node with a special name.isOfTag::(TagName->Bool)->XmlFilterisOfTag=isOfNode.isOfTagNode-- |-- test whether the node of a tree is a XTag node or a XPi node with an attibute of a specific name---- see also: 'isAttr', 'hasNsAttr'hasAttr::String->XmlFilterhasAttran=(getAttrl.>isAttran)`guards`this-- |-- test whether the tree is a XTag node with an attibute of a specific local name and namespace uri---- see also: 'hasAttr', 'isNsAttr'hasNsAttr::String->String->XmlFilterhasNsAttranns=(getAttrl.>isNsAttranns)`guards`this-- |-- test whether the given node is a XTag node or a XPI node with an attribute with a value with a specific property.-- In case of a match, the attribute value represented by a text node is returned as single element list,-- else the empty list is the result.---- see also : 'getValue'hasValue::String->(String->Bool)->XmlFilterhasValueapt|(not.null)att&&pval=xtextval|otherwise=[]whereatt=getAttrl.>isAttra$tval=xshow.getChildren$$att-- |-- test whether the tree is a processing instruction with a given name.isPi::String->XmlFilterisPipn=isOfNode(isPiNodepn)-- |-- test whether the tree is a \<?xml ... ?\> declarationisXmlPi::XmlFilterisXmlPi=isPit_xml-- |-- test whether the root of a tree contains a processing instruction of a special name.isOfPi::(TagName->Bool)->XmlFilterisOfPi=isOfNode.isOfPiNode-- ------------------------------------------------------------------------------- simple XNode Filter predicates---- |-- test whether the root of a tree contains a CDATA node.isXCdata::XmlFilterisXCdata=isOfNodeisXCdataNode-- |-- test whether the root of a tree contains a character reference node.isXCharRef::XmlFilterisXCharRef=isOfNodeisXCharRefNode-- |-- test whether the root of a tree contains a comment node.isXCmt::XmlFilterisXCmt=isOfNodeisXCmtNode-- |-- test whether the root of a tree contains a DTD part.isXDTD::XmlFilterisXDTD=isOfNodeisXDTDNode-- |-- test whether the root of a tree contains an entity reference node.isXEntityRef::XmlFilterisXEntityRef=isOfNodeisXEntityRefNode-- |-- test whether the root of a tree contains an error node.isXError::XmlFilterisXError=isOfNodeisXErrorNode-- |-- test whether the root of a tree contains a processing instruction node.isXPi::XmlFilterisXPi=isOfNodeisXPiNode-- |-- test whether the root of a tree contains a tag node.isXTag::XmlFilterisXTag=isOfNodeisXTagNode-- |-- test whether the root of a tree contains an attribute node.isXAttr::XmlFilterisXAttr=isOfNodeisXAttrNode-- |-- test whether the root of a tree is an attribute node for a given attribute nameisAttr::String->XmlFilterisAttran=isOfNode(isAttrNodean)-- |-- namespace aware test whether the tree contains an attribute node. Parameters are the local part of the atribute name and the namespace.-- Only usable after namespace propagation.---- see also: 'isNsTag', 'isAttr', 'hasNsAttr'isNsAttr::String->String->XmlFilterisNsAttrlpns=isOfAttr(\a->localParta==lp&&namespaceUria==ns)-- |-- general test for an attribute nameisOfAttr::(AttrName->Bool)->XmlFilterisOfAttr=isOfNode.isOfAttrNode-- |-- test whether the root of a tree contains a text node.isXText::XmlFilterisXText=isOfNodeisXTextNode-- |-- test whether the root of a tree contains a special text.isText::String->XmlFilterisTextt=isOfNode(isTextNodet)-- |-- test whether the root of a tree contains a text node with a special propertyisOfText::(String->Bool)->XmlFilterisOfText=isOfNode.isOfTextNode-- |-- test whether the root of a tree contains a text node only with whitespace.isWhiteSpace::XmlFilterisWhiteSpace=isOfNodeisWSwhereisWSn=isXTextNoden&&allisXmlSpaceChar(textOfXNoden)-- ---------------------------------------------------------------- XDTD Predicates-- |-- test whether the root of a tree contains a DOCTYPE DTD part.isDoctype::XmlFilterisDoctype=isOfNode(isDTDElemNodeDOCTYPE)-- |-- test whether the root of a tree contains an ATTLIST DTD part.isAttlist::XmlFilterisAttlist=isOfNode(isDTDElemNodeATTLIST)-- |-- test whether the root of a tree contains an ELEMENT DTD part.isElement::XmlFilterisElement=isOfNode(isDTDElemNodeELEMENT)-- |-- test whether the root of a tree contains an ENTITY DTD part.isEntity::XmlFilterisEntity=isOfNode(isDTDElemNodeENTITY)-- |-- test whether the root of a tree contains a parameter ENTITY reference.isPeRef::XmlFilterisPeRef=isOfNode(isDTDElemNodePEREF)-- |-- test whether the root of a tree contains a DTD name part.isDTDName::XmlFilterisDTDName=isOfNode(isDTDElemNodeNAME)-- |-- test whether the root of a tree contains a conditional section DTD part.isCondSect::XmlFilterisCondSect=isOfNode(isDTDElemNodeCONDSECT)-- |-- test whether the root of a tree contains a parameter entity declaration.isParameterEntity::XmlFilterisParameterEntity=isOfNode(isDTDElemNodePENTITY)-- |-- test whether the root of a tree contains a NOTATION DTD part.isNotation::XmlFilterisNotation=isOfNode(isDTDElemNodeNOTATION)-- ATTLIST predicatesisDefaultAttrKind::XmlFilterisDefaultAttrKind=isOf(a_kind`ofDTDequals`k_default)isEnumAttrType::XmlFilterisEnumAttrType=isOf(a_type`ofDTDequals`k_enumeration)isFixedAttrKind::XmlFilterisFixedAttrKind=isOf(a_kind`ofDTDequals`k_fixed)isIdAttrType::XmlFilterisIdAttrType=isOf(a_type`ofDTDequals`k_id)isIdRefAttrType::XmlFilterisIdRefAttrType=isOf((`elem`[k_idref,k_idrefs]).valueOfDTDa_type)isNotationAttrType::XmlFilterisNotationAttrType=isOf(a_type`ofDTDequals`k_notation)isRequiredAttrKind::XmlFilterisRequiredAttrKind=isOf(a_kind`ofDTDequals`k_required)isAttlistParameterEntity::XmlFilterisAttlistParameterEntity=isAttlist.>isOf(a_type`ofDTDequals`k_peref)-- ELEMENT predicatesisEmptyElement::XmlFilterisEmptyElement=isOf(a_type`ofDTDequals`k_empty)isMixedContentElement::XmlFilterisMixedContentElement=isOf(a_type`ofDTDequals`v_mixed)isElemWithContent::XmlFilterisElemWithContent=isElement.>isOf((`elem`[v_mixed,v_children]).valueOfDTDa_type)isAttlistOfElement::String->XmlFilterisAttlistOfElementel=isAttlist.>isOf(a_name`ofDTDequals`el)isElemContentParamEntity::XmlFilterisElemContentParamEntity=isElement.>isOf(a_type`ofDTDequals`k_peref)-- ENTITY predicatesisUnparsedEntity::XmlFilterisUnparsedEntity=isOf(hasEntryk_ndata.attrlOfDTD)isExternalParameterEntity::XmlFilterisExternalParameterEntity=isParameterEntity.>isOf(hasEntryk_system.attrlOfDTD)isInternalParameterEntity::XmlFilterisInternalParameterEntity=isParameterEntity.>isOf(not.hasEntryk_system.attrlOfDTD)-- ------------------------------------------------------------------------------- |-- test whether the root of a tree contains an error node for a warning.isWarning::XmlFilterisWarning=isOfNode$isErrorNodec_warn-- |-- test whether the root of a tree contains an error node for an error.isError::XmlFilterisError=isOfNode$isErrorNodec_err-- |-- test whether the root of a tree contains an error node for a fatal error.isFatalError::XmlFilterisFatalError=isOfNode$isErrorNodec_fatal-- --------------------------------------------------------------------------------- constructor filter-- |-- constructor filter for a tag node.-- a new tree is constructed.-- the attributes and the children are computed by applying the aproprate filter to the input tree---- * 1.parameter n : the tag name---- - 2.parameter af : the filter for the attribute list---- - 3.parameter cf : the filter for the children---- - returns : the constructor filtermkXTag::String->XmlFilter->XmlFilter->XmlFiltermkXTagnafcf=\t->[mkXTagTreen(aft)(cft)]-- | Version with qualified names of 'mkXTag'mkQTag::QName->XmlFilter->XmlFilter->XmlFiltermkQTagqafcf=\t->[mkQTagTreeq(aft)(cft)]-- |-- constructor filter for a tag node.-- a new tree is constructed.-- the attributes and the children are computed by applying the aproprate filter to the input tree---- * 1.parameter n : the tag name in form of prefix:localpart---- - 2.parameter ns: the namespace uri---- - 3.parameter af : the filter for the attribute list---- - 4.parameter cf : the filter for the children---- - returns : the constructor filtermkXNsTag::String->String->XmlFilter->XmlFilter->XmlFiltermkXNsTagnnsafcf=\t->[mkXNsTagTreenns(aft)(cft)]-- |-- filter for attribute construction.-- a new tree with attribute name and a value computed by a filter-- is build.mkXAttr::String->XmlFilter->XmlFiltermkXAttrnaf=\t->[mkXAttrTreen(aft)]-- | Qualified version 'mkXAttr'mkQAttr::QName->XmlFilter->XmlFiltermkQAttrqaf=\t->[mkQAttrTreeq(aft)]-- |-- filter for attribute construction.-- a new tree with attribute name and namespace and a value computed by a filter-- is build.mkXNsAttr::String->String->XmlFilter->XmlFiltermkXNsAttrnnsaf=\t->[mkXNsAttrTreenns(aft)]-- |-- constructor filter for a text node.-- a new tree is constructed.-- the input tree is ignored.mkXText::String->XmlFiltermkXText=mkNTree.mkXTextTree-- |-- constructor filter for a character reference node.-- a new tree is constructed.-- the input tree is ignored.mkXCharRef::Int->XmlFiltermkXCharRef=mkNTree.mkXCharRefTree-- |-- constructor filter for an entity reference node.-- a new tree is constructed.-- the input tree is ignored.mkXEntityRef::String->XmlFiltermkXEntityRef=mkNTree.mkXEntityRefTree-- |-- constructor filter for a comment node.-- a new tree is constructed.-- the xml string representation of the filter result-- forms the commentmkXCmt::XmlFilter->XmlFiltermkXCmtcf=\t->[mkXCmtTree((xshow.cf)t)]-- |-- constructor filter for a DTD part.-- a new tree is constructed.-- the input tree is ignored.mkXDTD::DTDElem->Attributes->XmlTrees->XmlFiltermkXDTDnal=mkNTree.mkXDTDTreenal-- |-- constructor filter for a CDATA section node.-- a new tree is constructed.-- the input tree is ignored.mkXCdata::XmlFilter->XmlFiltermkXCdatacf=\t->[mkXCdataTree((xshow.cf)t)]-- |-- constructor filter for a processing instruction-- a new tree is constructed from the text representation-- of the input treemkXPi::String->XmlFilter->XmlFiltermkXPipiNamecf=\t->[mkXPiTreepiName((xshow.cf)t)]-- |-- constructor filter for an error message node.-- a new tree is constructed.-- the input tree is ignored.mkXError::Int->String->XmlFiltermkXErrorls=this.mkXErrorTreels.this-- --------------------------------------------------------------------------------- selector filters-- |-- filter for selecting the name of a tag node, an attribute node or a pi node.-- Result of the filter is a single element list with a text node or the empty listgetName::XmlFiltergetNamet|nulls=[]|otherwise=xtextswheres=nameOft-- |-- filter for selecting the attibute listgetAttrl::XmlFiltergetAttrl=selAttrl.getNodewhereselAttrl(XTag_al)=alselAttrl(XPi_al)=alselAttrl_=[]-- |-- filter for selecting the value of an attribute in a tag node.-- Result of the filter is a single element list with a text node or the empty list---- see also : 'hasValue', 'getNsValue'getValue::String->XmlFiltergetValuea=xmlTreesToText.(getAttrl.>isAttra.>getChildren)-- |-- filter for selecting the value of an attribute with namespace in a tag node.-- Result of the filter is a single element list with a text node or the empty list---- see also : 'getValue', 'isNsAttr'getNsValue::String->String->XmlFiltergetNsValuelpns=xmlTreesToText.(getAttrl.>isNsAttrlpns.>getChildren)-- |-- filter for selecting an attribute of a DTD node.-- Result of the filter is a single element list with a text node or the empty listgetDTDValue::String->XmlFiltergetDTDValuea=xtext.valueOfDTDa-- |-- filter for selecting content of a comment.-- Result of the filter is a single element list with a text node or the empty listgetXCmt::XmlFiltergetXCmt=selCmt.getNodewhereselCmt(XCmtc)=xtextcselCmt_=[]-- |-- filter for selecting the CDATA content.-- Result of the filter is a single element list with a text node or the empty listgetXCdata::XmlFiltergetXCdata=selData.getNodewhereselData(XCdatad)=xtextdselData_=[]-- --------------------------------------------------------------------------------- edit filter-- |-- edit filter for changing the name of a tag node, an attribute or a pi.-- result of the filter is a single element list with a tag node or the empty listreplaceQName::String->XmlFilterreplaceQNamen=modifyQName(const(mkNamen))-- |-- edit filter for changing the text of a text node.-- result of the filter is a single element list with a text node or the empty list---- example for editing all text nodes of a tree with an edit function @f@:---- @processBottomUp (modifyText f \`when\` isXText)@modifyText::(String->String)->XmlFiltermodifyTextft@(NTreen_)|isXTextNoden=replaceNode(XText(f(textOfXNoden)))tmodifyText__=[]-- |-- edit filter for changing the name of a tag node.-- result of the filter is a single element list with a text node or the empty listmodifyQName::(TagName->TagName)->XmlFiltermodifyQNamef(NTree(XTagnal)cs)=[NTree(XTag(fn)al)cs]modifyQNamef(NTree(XPinal)cs)=[NTree(XPi(fn)al)cs]modifyQNamef(NTree(XAttrn)cs)=[NTree(XAttr(fn))cs]modifyQName__=[]-- ------------------------------------------------------------------------------- |-- process the attribute list of a tag node with a tree list filter.-- for other trees this filter acts like 'none'processAttrl::XmlSFilter->XmlFilterprocessAttrlft=replaceAttrl(fal)twhereal=getAttrlt-- |-- elementwise processing of the attributes of a tag.-- for other trees this filter acts like 'none'---- see also : 'processAttrl'processAttr::XmlFilter->XmlFilterprocessAttrf=processAttrl(f$$)-- |-- replace an attribute list-- to be renamed when replaceAttrl is eliminatedreplaceAttrl::XmlTrees->XmlFilterreplaceAttrlal(NTree(XTagn_al)cs)=[NTree(XTagnal)cs]replaceAttrlal(NTree(XPin_al)cs)=[NTree(XPinal)cs]replaceAttrl__=[]-- |-- delete an attribute from the attribute list of a tag treedel1Attr::String->XmlFilterdel1Attran=processAttr(none`when`isAttran)-- |-- add an attribute to the attribute list of a tag.-- If the attribute already exists, it\'s substituted,---- see also: 'sattr', '+='add1Attr::XmlTree->XmlFilteradd1Attra@(NTree(XAttran)_av)t=replaceAttrl(replaceal)twhereal=getAttrltreplace[]=[a]replace(a1:as)|satisfies(isAttr(qualifiedNamean))a1=a:as|otherwise=a1:replaceasadd1Attr_t=thist-- |-- adds an attribute list computed by a filter, uses 'add1Attr'.---- see also: '+='addAttrl::XmlFilter->XmlFilteraddAttrlattrFiltert=((foldl(.>)this.mapadd1Attr)al)twhereal=attrFiltert-- |-- add or change an attribute with a given string as value for a XTag or XPi tree,-- uses 'add1Attr'.addAttr::String->String->XmlFilteraddAttranav=add1Attr(mkXAttrTreean(ifnullavthen[]elsextextav))-- |-- add or change an attribute with an Int value.-- uses 'addAttr'.addAttrInt::String->Int->XmlFilteraddAttrIntanav=addAttran(showav)-- |-- edit filter for changing the value of an attribute in a tag node.-- result of the filter is a single element list with the tag node or the empty list.---- * 1.parameter n : the name of the attribute---- - 2.parameter f : the edit function for the attribute value---- - returns : the edit filtermodifyAttr::String->(String->String)->XmlFiltermodifyAttranf=processAttr(modifyValue`when`isAttran)wheremodifyValue=modifyChildren((modifyTextf$$).xmlTreesToText)-- |-- add or change an attribute of a DTD treeaddDTDAttr::String->String->XmlFilteraddDTDAttranav(NTree(XDTDeal)cs)=[NTree(XDTDe(addEntryanaval))cs]addDTDAttr___=[]-- --------------------------------------------------------------------------------- |-- convenient function for tag node tree construction---- infixl 7---- filter combinator for tag tree constrcution-- take a 1. filter for computing a tag node tree (or a whole list of tag node trees)-- then add all trees computed by the 2. filter to the attribute list when they represent attributes-- else append them to the list of children.---- if the 1. filter computes a list of tag nodes, the results of the 2. filter are added to all trees---- example: @ etag \"a\" += sattr \"href\" \"\#42\" += txt \"the answer\" @-- gives the tree @ \<a href=\"\#42\"\>the answer\<\/a\> @---- example: @ ( etag \"a\" +++ etag \"b\" ) += sattr \"x\" \"42\" @-- gives the tree @ \<a x=\"42\"\/\>\<b x=\"42\"\/\> @---- see also : 'etag', 'tag', 'add1Attr', 'modifyChildren', '++='(+=)::XmlFilter->XmlFilter->XmlFilter(+=)tfcft=concat[(isXTag`guards`(addaf.>addcf))$t'|t'<-tft]where(as,cs)=partition(satisfiesisXAttr).cf$taddaf|nullas=this|otherwise=addAttrl(constas)addcf|nullcs=this|otherwise=modifyChildren(++cs)-- |-- convenient filter function adding a whole list of trees, just for not writing to many ( ... ).---- infixl 7---- @ f ++= gl == f += cat gl @---- see also : '+='(++=)::XmlFilter->[XmlFilter]->XmlFiltertf++=cfs=tf+=catcfs-- --------------------------------------------------------------------------------- string access functions-- |-- combination of 'getValue' and conversion into a StringvalueOf::String->XmlTree->StringvalueOfa=xshow.getValuea-- |-- combination of 'getValue' and conversion to a IntintValueOf::String->XmlTree->IntintValueOfa=decimalStringToInt.valueOfa-- --------------------------------------------------------------------------------- convenient filter (short cuts)-- |-- variant of mkXTag with a list of filters for the attributes and a list of filters for the children.-- this variant leads to a more readable source for a complicated construction filter-- than the simple solution with a combination of 'mkXTag' and 'cat'.---- see also : 'mkXTag', 'stag', 'etag', 'cat', '+='tag::String->[XmlFilter]->[XmlFilter]->XmlFiltertagnafscfs=mkXTagn(catafs)(catcfs)-- |-- variant of tag, useful for tags without attributes and with a list of filters for-- constructing the children---- see also : 'mkXTag', 'tag', 'etag', 'cat', '+='stag::String->[XmlFilter]->XmlFilterstagncfs=mkXTagnnone(catcfs)-- |-- variant of tag, useful for tags with attributes but without children---- see also : 'mkXTag', 'tag', 'stag', 'etag', 'cat'atag::String->[XmlFilter]->XmlFilteratagncfs=mkXTagn(catcfs)none-- |-- Short cut for empty tags without attributes---- see also : 'tag', 'atag', 'stag', 'mkXTag' and '+='etag::String->XmlFilteretagn=mkXTagnnonenone-- | Qualified version of etagqetag::QName->XmlFilterqetagq=mkQTagqnonenone-- | Alias for mkQTagqtag::QName->XmlFilter->XmlFilter->XmlFilterqtag=mkQTag-- |-- filter for creating a document root node with a list of filters for the attributes and a list of filters for the document.---- see also : 'tag'rootTag::[XmlFilter]->[XmlFilter]->XmlFilterrootTagafscfs=mkXTagt_root(catafs)(catcfs)-- |-- Alias for 'mkXAttr'attr::String->XmlFilter->XmlFilterattr=mkXAttr-- | Alias for mkQAttrqattr::QName->XmlFilter->XmlFilterqattr=mkQAttr-- |-- short cut for attribute construction with string constants---- set also : 'attr', 'mkXAttr' and 'mkXText'sattr::String->String->XmlFiltersattrav=mkXAttra(mkXTextv)-- |-- short cut for 'mkXText'txt::String->XmlFiltertxt=mkXText-- |-- short cut for simple comment-- the input tree is ignored---- see also : 'mkXCmt'cmt::String->XmlFiltercmtc=mkXCmt(txtc)-- |-- short cut for generating simple processing instructions (spi)-- the input tree is ignored---- @spi \"xyz\" \"abc\"@ is equal to @mkXPi \"xyz\" (txt \"abc\")@-- (the name pi is already used in prelude)spi::String->String->XmlFilterspinc=mkXPin(txtc)-- |-- short cut for generating simple cdata sections,-- the input tree is ignoredcdata::String->XmlFiltercdatas=mkXCdata(txts)-- |-- DTD part generation with filter for attributes and children-- see also: 'mkXDTDTree'dtd::DTDElem->[XmlFilter]->[XmlFilter]->XmlFilterdtddtdpartafscfst=mkXDTDdtdpart(toAttrl.catafs$t)(catcfst)$t-- |-- short cut for mkXError c_warn.---- see also : 'mkXError'warn::String->XmlFilterwarn=mkXErrorc_warn-- |-- short cut for mkXError c_fatal.---- see also : 'mkXError'err::String->XmlFiltererr=mkXErrorc_err-- |-- short cut for mkXError c_fatal.---- see also : 'mkXError'fatal::String->XmlFilterfatal=mkXErrorc_fatal-- |-- check whether an option is set---- reads the value of an attribute, usually applied to a document root node,-- and checks if the value represents True. The following strings are interpreted-- as true: \"1\", \"True\", \"true\", \"yes\", \"Yes\".hasOption::String->XmlFilterhasOptionopt=getValueopt.>isOfTextisSetwhereisSetx=x`elem`["1","True","true","yes","Yes"]-- -----------------------------------------------------------------------------