xml-types 0.1.4 → 0.2
raw patch · 2 files changed
+158/−74 lines, 2 filesdep +containersdep ~base
Dependencies added: containers
Dependency ranges changed: base
Files
- Data/XML/Types.hs +156/−73
- xml-types.cabal +2/−1
Data/XML/Types.hs view
@@ -1,28 +1,26 @@--- Copyright (c) 2010 John Millikin+-- |+-- Module: Data.XML.Types+-- Copyright: 2010-2011 John Millikin+-- License: MIT ----- Permission is hereby granted, free of charge, to any person--- obtaining a copy of this software and associated documentation--- files (the "Software"), to deal in the Software without--- restriction, including without limitation the rights to use,--- copy, modify, merge, publish, distribute, sublicense, and/or sell--- copies of the Software, and to permit persons to whom the--- Software is furnished to do so, subject to the following--- conditions:+-- Maintainer: jmillikin@gmail.com+-- Portability: portable ----- The above copyright notice and this permission notice shall be--- included in all copies or substantial portions of the Software.+-- Basic types for representing XML. ----- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,--- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES--- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND--- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT--- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,--- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING--- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR--- OTHER DEALINGS IN THE SOFTWARE.-+-- 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 (..)@@ -32,38 +30,52 @@ -- ** Document body , Node (..) , Element (..)- , Attribute (..) , Content (..) , Name (..)- , Named (..) -- ** Doctypes , Doctype (..) , ExternalID (..)- , InternalSubset+ , DoctypeNode (..)+ , Declaration -- ** Incremental processing , Event (..) - -- * Predicates+ -- * Combinators+ + -- ** Filters , isElement , isInstruction , isContent , isComment , isNamed - -- * Filters- , nodeChildren+ -- ** Element traversal , elementChildren , elementContent+ , elementText+ + -- ** Node traversal+ , nodeChildren+ , nodeContent+ , nodeText+ + -- ** Attributes , hasAttribute- , position+ , hasAttributeText+ , attributeContent+ , attributeText ) where import Control.Monad ((>=>))-import Data.Text.Lazy (Text)-import qualified Data.Text.Lazy as T+import qualified Data.Map as M+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@@ -72,6 +84,9 @@ } deriving (Show, Eq) +instance Typeable Document where+ typeOf = typeString "Document"+ data Prologue = Prologue { prologueBefore :: [Miscellaneous] , prologueDoctype :: Maybe Doctype@@ -79,17 +94,26 @@ } 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@@ -97,24 +121,42 @@ | NodeComment Text deriving (Show, Eq) +instance Typeable Node where+ typeOf = typeString "Node"+ data Element = Element { elementName :: Name- , elementAttributes :: [Attribute]+ , elementAttributes :: M.Map Name [Content] , elementNodes :: [Node] } deriving (Show, Eq) -data Attribute = Attribute- { attributeName :: Name- , attributeContent :: [Content]- }- deriving (Show, Eq)+instance Typeable Element where+ typeOf = typeString "Element" data Content = ContentText Text- | ContentEntity 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@@ -122,20 +164,15 @@ } deriving (Show) --- | Ignores prefixes+instance Typeable Name where+ typeOf = typeString "Name"+ instance Eq Name where (==) = (==) `on` (\x -> (nameNamespace x, nameLocalName x)) --- | Ignores prefixes------ Since 0.1.3 instance Ord Name where compare = compare `on` (\x -> (nameNamespace x, nameLocalName x)) --- | Supports Clark notation; see <http://www.jclark.com/xml/xmlns.htm> and--- <http://infohost.nmt.edu/tcc/help/pubs/pylxml/etree-QName.html>------ Since 0.1.2 instance IsString Name where fromString "" = Name T.empty Nothing Nothing fromString full@('{':rest) = case break (== '}') rest of@@ -143,51 +180,78 @@ (ns, local) -> Name (T.pack (drop 1 local)) (Just (T.pack ns)) Nothing fromString local = Name (T.pack local) Nothing Nothing -class Named a where- getName :: a -> Name--instance Named Element where- getName = elementName--instance Named Attribute where- getName = attributeName- data Doctype = Doctype { doctypeName :: Text , doctypeExternalID :: Maybe ExternalID- , doctypeInternalSubsets :: [InternalSubset]+ , doctypeNodes :: [DoctypeNode] } deriving (Show, Eq) --- | Since 0.1.3 instance Ord Doctype where compare = compare `on` (\x -> (doctypeName x, doctypeExternalID x)) +instance Typeable Doctype where+ typeOf = typeString "Doctype"+ data ExternalID = SystemID Text | PublicID Text Text deriving (Show, Eq, Ord) -data InternalSubset = InternalSubset- -- TODO+instance Typeable ExternalID where+ typeOf = typeString "ExternalID"++data DoctypeNode+ = DoctypeDeclaration Declaration+ | DoctypeInstruction Instruction+ | DoctypeComment Text deriving (Show, Eq) +instance Typeable DoctypeNode where+ typeOf = typeString "DoctypeNode"++-- | Internal doctype declarations are still largely unimplemented. This+-- type will be populated and published in a later version of @xml-types@.+--+data Declaration+ = DeclareElement Text+ | DeclareAttributeList Text+ | DeclareEntity Text+ | DeclareNotation Text+ deriving (Show, Eq)++instance Typeable Declaration where+ typeOf = typeString "Declaration"+ -- | Some XML processing tools are incremental, and work in terms of events--- rather than node trees. Defining the event type here, even though it won't--- be useful to most users, allows these packages to interoperate more easily.+-- rather than node trees. The 'Event' type allows a document to be fully+-- specified as a sequence of events. ----- Since: 0.1.1+-- 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)+ | EventDeclaration Declaration+ | EventEndDoctype | EventInstruction Instruction- | EventDoctype Doctype- | EventBeginElement Name [Attribute]+ | EventBeginElement Name (M.Map 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 _ = []@@ -204,26 +268,45 @@ isComment (NodeComment t) = [t] isComment _ = [] -isNamed :: Named a => Name -> a -> [a]-isNamed n x = [x | getName x == n]+isNamed :: Name -> Element -> [Element]+isNamed n e = [e | elementName e == n] elementChildren :: Element -> [Element] elementChildren = elementNodes >=> isElement --- | Since 0.1.4 elementContent :: Element -> [Content] elementContent = elementNodes >=> isContent +elementText :: Element -> [Text]+elementText = elementContent >=> contentText+ nodeChildren :: Node -> [Node] nodeChildren = isElement >=> elementNodes -position :: Integer -> (a -> [b]) -> a -> [b]-position n f e = safeHead n (f e)+nodeContent :: Node -> [Content]+nodeContent = nodeChildren >=> isContent -safeHead :: Integer -> [a] -> [a]-safeHead _ [] = []-safeHead 0 (x:_) = [x]-safeHead n (_:xs) = safeHead (n - 1) xs+nodeText :: Node -> [Text]+nodeText = nodeContent >=> contentText -hasAttribute :: (Attribute -> [Attribute]) -> Element -> [Element]-hasAttribute f e = [e | not $ null (elementAttributes e >>= f)]+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 = M.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,5 +1,5 @@ name: xml-types-version: 0.1.4+version: 0.2 synopsis: Basic types for representing XML license: MIT license-file: license.txt@@ -21,6 +21,7 @@ build-depends: base >=3 && < 5 , text+ , containers exposed-modules: Data.XML.Types