packages feed

xml-types 0.3 → 0.3.1

raw patch · 3 files changed

+299/−292 lines, 3 files

Files

− Data/XML/Types.hs
@@ -1,288 +0,0 @@--- |--- Module: Data.XML.Types--- Copyright: 2010-2011 John Millikin--- License: MIT------ Maintainer: jmillikin@gmail.com--- Portability: portable------ Basic types for representing XML.------ The idea is to have a full set of appropriate types, which various XML--- libraries can share. Instead of having equivalent-but-incompatible types--- for every binding, parser, or client, they all share the same types can--- can thus interoperate easily.------ This library contains complete types for most parts of an XML document,--- including the prologue, node tree, and doctype. Some basic combinators--- are included for common tasks, including traversing the node tree and--- filtering children.----module Data.XML.Types-	( -- * Types-	-	  -- ** Document prologue-	  Document (..)-	, Prologue (..)-	, Instruction (..)-	, Miscellaneous (..)-	-	-- ** Document body-	, Node (..)-	, Element (..)-	, Content (..)-	, Name (..)-	-	-- ** Doctypes-	, Doctype (..)-	, ExternalID (..)-	-	-- ** Incremental processing-	, Event (..)-	-	-- * Combinators-	-	-- ** Filters-	, isElement-	, isInstruction-	, isContent-	, isComment-	, isNamed-	-	-- ** Element traversal-	, elementChildren-	, elementContent-	, elementText-	-	-- ** Node traversal-	, nodeChildren-	, nodeContent-	, nodeText-	-	-- ** Attributes-	, hasAttribute-	, hasAttributeText-	, attributeContent-	, attributeText-	) where-import Control.Monad ((>=>))-import Data.Maybe (isJust)-import Data.Text (Text)-import qualified Data.Text as T-import Data.String (IsString, fromString)-import Data.Function (on)-import Data.Typeable ( Typeable, TypeRep, typeOf-                     , mkTyConApp, mkTyCon)--data Document = Document-	{ documentPrologue :: Prologue-	, documentRoot :: Element-	, documentEpilogue :: [Miscellaneous]-	}-	deriving (Show, Eq)--instance Typeable Document where-	typeOf = typeString "Document"--data Prologue = Prologue-	{ prologueBefore :: [Miscellaneous]-	, prologueDoctype :: Maybe Doctype-	, prologueAfter :: [Miscellaneous]-	}-	deriving (Show, Eq)--instance Typeable Prologue where-	typeOf = typeString "Prologue"--data Instruction = Instruction-	{ instructionTarget :: Text-	, instructionData :: Text-	}-	deriving (Show, Eq, Ord)--instance Typeable Instruction where-	typeOf = typeString "Instruction"--data Miscellaneous-	= MiscInstruction Instruction-	| MiscComment Text-	deriving (Show, Eq)--instance Typeable Miscellaneous where-	typeOf = typeString "Miscellaneous"--data Node-	= NodeElement Element-	| NodeInstruction Instruction-	| NodeContent Content-	| NodeComment Text-	deriving (Show, Eq)--instance Typeable Node where-	typeOf = typeString "Node"--data Element = Element-	{ elementName :: Name-	, elementAttributes :: [(Name, [Content])]-	, elementNodes :: [Node]-	}-	deriving (Show, Eq)--instance Typeable Element where-	typeOf = typeString "Element"--data Content-	= ContentText Text-	| ContentEntity Text -- ^ For pass-through parsing-	deriving (Show, Eq)--instance Typeable Content where-	typeOf = typeString "Content"---- | A fully qualified name.------ Prefixes are not semantically important; they are included only to--- simplify pass-through parsing. When comparing names with 'Eq' or 'Ord'--- methods, prefixes are ignored.------ The @IsString@ instance supports Clark notation; see--- <http://www.jclark.com/xml/xmlns.htm> and--- <http://infohost.nmt.edu/tcc/help/pubs/pylxml/etree-QName.html>. Use--- the @OverloadedStrings@ language extension for very simple @Name@--- construction:------ > myname :: Name--- > myname = "{http://example.com/ns/my-namespace}my-name"----data Name = Name-	{ nameLocalName :: Text-	, nameNamespace :: Maybe Text-	, namePrefix :: Maybe Text-	}-	deriving (Show)--instance Typeable Name where-	typeOf = typeString "Name"--instance Eq Name where-	(==) = (==) `on` (\x -> (nameNamespace x, nameLocalName x))--instance Ord Name where-	compare = compare `on` (\x -> (nameNamespace x, nameLocalName x))--instance IsString Name where-	fromString "" = Name T.empty Nothing Nothing-	fromString full@('{':rest) = case break (== '}') rest of-		(_, "") -> error ("Invalid Clark notation: " ++ show full)-		(ns, local) -> Name (T.pack (drop 1 local)) (Just (T.pack ns)) Nothing-	fromString local = Name (T.pack local) Nothing Nothing---- | Note: due to the incredible complexity of DTDs, this type only supports--- external subsets. I've tried adding internal subset types, but they--- quickly gain more code than the rest of this module put together.------ It is possible that some future version of this library might support--- internal subsets, but I am no longer actively working on adding them.-data Doctype = Doctype-	{ doctypeName :: Text-	, doctypeID :: Maybe ExternalID-	}-	deriving (Show, Eq, Ord)--instance Typeable Doctype where-	typeOf = typeString "Doctype"--data ExternalID-	= SystemID Text-	| PublicID Text Text-	deriving (Show, Eq, Ord)--instance Typeable ExternalID where-	typeOf = typeString "ExternalID"---- | Some XML processing tools are incremental, and work in terms of events--- rather than node trees. The 'Event' type allows a document to be fully--- specified as a sequence of events.------ Event-based XML libraries include:------ * <http://hackage.haskell.org/package/xml-enumerator>------ * <http://hackage.haskell.org/package/libxml-enumerator>------ * <http://hackage.haskell.org/package/expat-enumerator>----data Event-	= EventBeginDocument-	| EventEndDocument-	| EventBeginDoctype Text (Maybe ExternalID)-	| EventEndDoctype-	| EventInstruction Instruction-	| EventBeginElement Name [(Name, [Content])]-	| EventEndElement Name-	| EventContent Content-	| EventComment Text-	| EventCDATA Text-	deriving (Show, Eq)--instance Typeable Event where-	typeOf = typeString "Event"--isElement :: Node -> [Element]-isElement (NodeElement e) = [e]-isElement _ = []--isInstruction :: Node -> [Instruction]-isInstruction (NodeInstruction i) = [i]-isInstruction _ = []--isContent :: Node -> [Content]-isContent (NodeContent c) = [c]-isContent _ = []--isComment :: Node -> [Text]-isComment (NodeComment t) = [t]-isComment _ = []--isNamed :: Name -> Element -> [Element]-isNamed n e = [e | elementName e == n]--elementChildren :: Element -> [Element]-elementChildren = elementNodes >=> isElement--elementContent :: Element -> [Content]-elementContent = elementNodes >=> isContent--elementText :: Element -> [Text]-elementText = elementContent >=> contentText--nodeChildren :: Node -> [Node]-nodeChildren = isElement >=> elementNodes--nodeContent :: Node -> [Content]-nodeContent = nodeChildren >=> isContent--nodeText :: Node -> [Text]-nodeText = nodeContent >=> contentText--hasAttribute :: Name -> Element -> [Element]-hasAttribute name e = [e | isJust (attributeContent name e)]--hasAttributeText :: Name -> (Text -> Bool) -> Element -> [Element]-hasAttributeText name p e = [e | maybe False p (attributeText name e)]--attributeContent :: Name -> Element -> Maybe [Content]-attributeContent name e = lookup name (elementAttributes e)--attributeText :: Name -> Element -> Maybe Text-attributeText name e = fmap contentFlat (attributeContent name e)--contentText :: Content -> [Text]-contentText (ContentText t) = [t]-contentText (ContentEntity entity) = [T.pack "&", entity, T.pack ";"]--contentFlat :: [Content] -> Text-contentFlat cs = T.concat (cs >>= contentText)--typeString :: String -> a -> TypeRep-typeString str _ = mkTyConApp (mkTyCon ("Data.XML.Types." ++ str)) []
+ lib/Data/XML/Types.hs view
@@ -0,0 +1,288 @@+-- |+-- Module: Data.XML.Types+-- Copyright: 2010-2011 John Millikin+-- License: MIT+--+-- Maintainer: jmillikin@gmail.com+-- Portability: portable+--+-- Basic types for representing XML.+--+-- The idea is to have a full set of appropriate types, which various XML+-- libraries can share. Instead of having equivalent-but-incompatible types+-- for every binding, parser, or client, they all share the same types can+-- can thus interoperate easily.+--+-- This library contains complete types for most parts of an XML document,+-- including the prologue, node tree, and doctype. Some basic combinators+-- are included for common tasks, including traversing the node tree and+-- filtering children.+--+module Data.XML.Types+	( -- * Types+	+	  -- ** Document prologue+	  Document (..)+	, Prologue (..)+	, Instruction (..)+	, Miscellaneous (..)+	+	-- ** Document body+	, Node (..)+	, Element (..)+	, Content (..)+	, Name (..)+	+	-- ** Doctypes+	, Doctype (..)+	, ExternalID (..)+	+	-- ** Incremental processing+	, Event (..)+	+	-- * Combinators+	+	-- ** Filters+	, isElement+	, isInstruction+	, isContent+	, isComment+	, isNamed+	+	-- ** Element traversal+	, elementChildren+	, elementContent+	, elementText+	+	-- ** Node traversal+	, nodeChildren+	, nodeContent+	, nodeText+	+	-- ** Attributes+	, hasAttribute+	, hasAttributeText+	, attributeContent+	, attributeText+	) where+import Control.Monad ((>=>))+import Data.Maybe (isJust)+import Data.Text (Text)+import qualified Data.Text as T+import Data.String (IsString, fromString)+import Data.Function (on)+import Data.Typeable ( Typeable, TypeRep, typeOf+                     , mkTyConApp, mkTyCon)++data Document = Document+	{ documentPrologue :: Prologue+	, documentRoot :: Element+	, documentEpilogue :: [Miscellaneous]+	}+	deriving (Show, Eq, Ord)++instance Typeable Document where+	typeOf = typeString "Document"++data Prologue = Prologue+	{ prologueBefore :: [Miscellaneous]+	, prologueDoctype :: Maybe Doctype+	, prologueAfter :: [Miscellaneous]+	}+	deriving (Show, Eq, Ord)++instance Typeable Prologue where+	typeOf = typeString "Prologue"++data Instruction = Instruction+	{ instructionTarget :: Text+	, instructionData :: Text+	}+	deriving (Show, Eq, Ord)++instance Typeable Instruction where+	typeOf = typeString "Instruction"++data Miscellaneous+	= MiscInstruction Instruction+	| MiscComment Text+	deriving (Show, Eq, Ord)++instance Typeable Miscellaneous where+	typeOf = typeString "Miscellaneous"++data Node+	= NodeElement Element+	| NodeInstruction Instruction+	| NodeContent Content+	| NodeComment Text+	deriving (Show, Eq, Ord)++instance Typeable Node where+	typeOf = typeString "Node"++data Element = Element+	{ elementName :: Name+	, elementAttributes :: [(Name, [Content])]+	, elementNodes :: [Node]+	}+	deriving (Show, Eq, Ord)++instance Typeable Element where+	typeOf = typeString "Element"++data Content+	= ContentText Text+	| ContentEntity Text -- ^ For pass-through parsing+	deriving (Show, Eq, Ord)++instance Typeable Content where+	typeOf = typeString "Content"++-- | A fully qualified name.+--+-- Prefixes are not semantically important; they are included only to+-- simplify pass-through parsing. When comparing names with 'Eq' or 'Ord'+-- methods, prefixes are ignored.+--+-- The @IsString@ instance supports Clark notation; see+-- <http://www.jclark.com/xml/xmlns.htm> and+-- <http://infohost.nmt.edu/tcc/help/pubs/pylxml/etree-QName.html>. Use+-- the @OverloadedStrings@ language extension for very simple @Name@+-- construction:+--+-- > myname :: Name+-- > myname = "{http://example.com/ns/my-namespace}my-name"+--+data Name = Name+	{ nameLocalName :: Text+	, nameNamespace :: Maybe Text+	, namePrefix :: Maybe Text+	}+	deriving (Show)++instance Typeable Name where+	typeOf = typeString "Name"++instance Eq Name where+	(==) = (==) `on` (\x -> (nameNamespace x, nameLocalName x))++instance Ord Name where+	compare = compare `on` (\x -> (nameNamespace x, nameLocalName x))++instance IsString Name where+	fromString "" = Name T.empty Nothing Nothing+	fromString full@('{':rest) = case break (== '}') rest of+		(_, "") -> error ("Invalid Clark notation: " ++ show full)+		(ns, local) -> Name (T.pack (drop 1 local)) (Just (T.pack ns)) Nothing+	fromString local = Name (T.pack local) Nothing Nothing++-- | Note: due to the incredible complexity of DTDs, this type only supports+-- external subsets. I've tried adding internal subset types, but they+-- quickly gain more code than the rest of this module put together.+--+-- It is possible that some future version of this library might support+-- internal subsets, but I am no longer actively working on adding them.+data Doctype = Doctype+	{ doctypeName :: Text+	, doctypeID :: Maybe ExternalID+	}+	deriving (Show, Eq, Ord)++instance Typeable Doctype where+	typeOf = typeString "Doctype"++data ExternalID+	= SystemID Text+	| PublicID Text Text+	deriving (Show, Eq, Ord)++instance Typeable ExternalID where+	typeOf = typeString "ExternalID"++-- | Some XML processing tools are incremental, and work in terms of events+-- rather than node trees. The 'Event' type allows a document to be fully+-- specified as a sequence of events.+--+-- Event-based XML libraries include:+--+-- * <http://hackage.haskell.org/package/xml-enumerator>+--+-- * <http://hackage.haskell.org/package/libxml-enumerator>+--+-- * <http://hackage.haskell.org/package/expat-enumerator>+--+data Event+	= EventBeginDocument+	| EventEndDocument+	| EventBeginDoctype Text (Maybe ExternalID)+	| EventEndDoctype+	| EventInstruction Instruction+	| EventBeginElement Name [(Name, [Content])]+	| EventEndElement Name+	| EventContent Content+	| EventComment Text+	| EventCDATA Text+	deriving (Show, Eq, Ord)++instance Typeable Event where+	typeOf = typeString "Event"++isElement :: Node -> [Element]+isElement (NodeElement e) = [e]+isElement _ = []++isInstruction :: Node -> [Instruction]+isInstruction (NodeInstruction i) = [i]+isInstruction _ = []++isContent :: Node -> [Content]+isContent (NodeContent c) = [c]+isContent _ = []++isComment :: Node -> [Text]+isComment (NodeComment t) = [t]+isComment _ = []++isNamed :: Name -> Element -> [Element]+isNamed n e = [e | elementName e == n]++elementChildren :: Element -> [Element]+elementChildren = elementNodes >=> isElement++elementContent :: Element -> [Content]+elementContent = elementNodes >=> isContent++elementText :: Element -> [Text]+elementText = elementContent >=> contentText++nodeChildren :: Node -> [Node]+nodeChildren = isElement >=> elementNodes++nodeContent :: Node -> [Content]+nodeContent = nodeChildren >=> isContent++nodeText :: Node -> [Text]+nodeText = nodeContent >=> contentText++hasAttribute :: Name -> Element -> [Element]+hasAttribute name e = [e | isJust (attributeContent name e)]++hasAttributeText :: Name -> (Text -> Bool) -> Element -> [Element]+hasAttributeText name p e = [e | maybe False p (attributeText name e)]++attributeContent :: Name -> Element -> Maybe [Content]+attributeContent name e = lookup name (elementAttributes e)++attributeText :: Name -> Element -> Maybe Text+attributeText name e = fmap contentFlat (attributeContent name e)++contentText :: Content -> [Text]+contentText (ContentText t) = [t]+contentText (ContentEntity entity) = [T.pack "&", entity, T.pack ";"]++contentFlat :: [Content] -> Text+contentFlat cs = T.concat (cs >>= contentText)++typeString :: String -> a -> TypeRep+typeString str _ = mkTyConApp (mkTyCon ("Data.XML.Types." ++ str)) []
xml-types.cabal view
@@ -1,25 +1,32 @@ name: xml-types-version: 0.3+version: 0.3.1 synopsis: Basic types for representing XML license: MIT license-file: license.txt author: John Millikin <jmillikin@gmail.com> maintainer: jmillikin@gmail.com build-type: Simple-cabal-version: >=1.6+cabal-version: >= 1.6 category: Text, XML stability: experimental+homepage: https://john-millikin.com/software/haskell-xml/ bug-reports: mailto:jmillikin@gmail.com  source-repository head   type: bazaar-  location: http://john-millikin.com/software/xml-types/+  location: https://john-millikin.com/branches/xml-types/0.3/ +source-repository this+  type: bazaar+  location: https://john-millikin.com/branches/xml-types/0.3/+  tag: xml-types_0.3.1+ library   ghc-options: -Wall+  hs-source-dirs: lib    build-depends:-      base >=3 && < 5+      base >= 3 && < 5     , text    exposed-modules: