packages feed

hxt-7.3: src/Text/XML/HXT/Arrow/Pickle/Schema.hs

-- ------------------------------------------------------------

{- |
   Module     : Text.XML.HXT.Arrow.Pickle.Schema
   Copyright  : Copyright (C) 2005 Uwe Schmidt
   License    : MIT

   Maintainer : Uwe Schmidt (uwe@fh-wedel.de)
   Stability  : experimental
   Portability: portable
   Version    : $Id$

Datatypes and functions for building a content model
for XML picklers. A schema is part of every pickler
and can be used to derive a corrensponding DTD (or Relax NG schema).
This schema further enables checking the picklers.

-}

-- ------------------------------------------------------------

module Text.XML.HXT.Arrow.Pickle.Schema
where

import Text.XML.HXT.DOM.XmlKeywords (k_required, k_implied, k_fixed)

-- ------------------------------------------------------------

-- | The datatype for modelling the structure of an

data Schema			= Any
				| PCData	SchemaRestriction
				| CData		Kind	SchemaRestriction
				| Option	Schema
				| Seq		[Schema]
				| Alt		[Schema]
				| Rep	Int Int Schema
				| Element	Name	Schema
				| Attribute	Name	Schema
				| ElemRef	Name
				  deriving (Show)

type Name			= String
type Kind               	= String	-- k_fixed, k_implies, k_required
type Schemas			= [Schema]

data SchemaRestriction		= FixedValue	String
				| DTDAttrType	String
				| ValEnum	[String]
				| RegEx		String
				| XmlSchemaType	String
				  deriving (Eq, Show)

isScElem		:: Schema -> Bool
isScElem (Element _ _)	= True
isScElem _		= False

isScElemRef		:: Schema -> Bool
isScElemRef (ElemRef _)	= True
isScElemRef _		= False

isScPCData		:: Schema -> Bool
isScPCData (PCData _)	= True
isScPCData _		= False

isScCData		:: Schema -> Bool
isScCData (CData _ _)	= True
isScCData _		= False

isScSARE		:: Schema -> Bool
isScSARE (Seq _)	= True
isScSARE (Alt _)	= True
isScSARE (Rep _ _ _)	= True
isScSARE (ElemRef _)	= True
isScSARE _		= False

emptyText			:: SchemaRestriction
emptyText			= restrictRegEx ".*"

noneEmptyText			:: SchemaRestriction
noneEmptyText			= restrictRegEx ".+"

restrictRegEx			:: String -> SchemaRestriction
restrictRegEx			= RegEx

restrictDTDAttrType		:: String -> SchemaRestriction
restrictDTDAttrType		= DTDAttrType

restrictEnum			:: [String] -> SchemaRestriction
restrictEnum			= ValEnum

restrictOption			:: SchemaRestriction -> SchemaRestriction
restrictOption (RegEx re)	= restrictRegEx $ "(" ++ re ++ ")?"
restrictOption r		= r

-- ------------------------------------------------------------

-- smart constructors for Schema datatype

scEmpty				:: Schema
scEmpty				= Seq []

scRequiredAttr			:: SchemaRestriction -> Schema
scRequiredAttr re		= CData k_required re

scImpliedAttr			:: SchemaRestriction -> Schema
scImpliedAttr re		= CData k_implied re

scFixedCData			:: String -> Schema
scFixedCData v			= CData k_fixed (FixedValue v)

scRestrict			:: SchemaRestriction -> Schema -> Schema
scRestrict re (CData k _)	= CData k re
scRestrict re (PCData _)	= PCData re
scRestrict _ sc			= sc

scSeq				:: Schema -> Schema -> Schema
scSeq (Seq [])   sc2		= sc2
scSeq sc1        (Seq [])	= sc1
scSeq (Seq scs1) (Seq scs2)	= Seq (scs1 ++ scs2)	-- prevent nested Seq expr
scSeq (Seq scs1) sc2		= Seq (scs1 ++ [sc2])
scSeq sc1        (Seq scs2)	= Seq (sc1  :  scs2)
scSeq sc1        sc2		= Seq [sc1,sc2]

scSeqs				:: [Schema] -> Schema
scSeqs				= foldl scSeq scEmpty

scNull				:: Schema
scNull				= Alt []

scAlt				:: Schema -> Schema -> Schema
scAlt (Alt [])   sc2		= sc2
scAlt sc1        (Alt [])	= sc1
scAlt (Alt scs1) (Alt scs2)	= Alt (scs1 ++ scs2)	-- prevent nested Alt expr
scAlt (Alt scs1) sc2		= Alt (scs1 ++ [sc2])
scAlt sc1        (Alt scs2)	= Alt (sc1  :  scs2)
scAlt sc1        sc2		= Alt [sc1,sc2]

scAlts		:: [Schema] -> Schema
scAlts		= foldl scAlt scNull

scOption	:: Schema -> Schema
scOption     (Seq [])		= scEmpty

scOption (PCData re)
    | re == noneEmptyText	= PCData emptyText
    | otherwise			= PCData (restrictOption re)

scOption (Attribute n sc2)	= Attribute n (scOptionAttr sc2)
    where
    scOptionAttr (CData _ re)	= scImpliedAttr re
    scOptionAttr sc'		= sc'

scOption sc1			= Rep 0 1 sc1

scList		:: Int -> Int -> Schema -> Schema
scList l u sc1  = Rep l u sc1

scElem		:: String -> Schema -> Schema
scElem n sc1	= Element n sc1

scAttr		:: String -> Schema -> Schema
scAttr n sc1	= Attribute n (scAttrCont sc1)
    where
    scAttrCont (PCData re)	= scRequiredAttr re
    scAttrCont sc'		= sc'

-- ------------------------------------------------------------