-- | -- This module provides functions for validating XML documents represented as -- XmlTree. -- Unlike other popular XML validation tools the validation functions return -- a list of errors instead of aborting after the first error was found. -- -- Note: The validation process has been split into validation and transformation! -- If @validate@ did not report any errors, @transform@ -- should be called, to change the document the way a validating parser -- is expected to do. -- -- Author : .\\artin Schmidt module Text.XML.HXT.Validator.ValidationFilter ( getDTDSubset , validate , validateDTD , validateDoc , removeDoublicateDefs , transform ) where import Text.XML.HXT.DOM.XmlTree import qualified Text.XML.HXT.Validator.DTDValidation as DTDValidation import qualified Text.XML.HXT.Validator.DocValidation as DocValidation import qualified Text.XML.HXT.Validator.IdValidation as IdValidation import qualified Text.XML.HXT.Validator.DocTransformation as DocTransformation -- | -- Main validation filter. Check if the DTD and the document are valid. -- -- -- - returns : a function which expects a complete document as XmlTree input -- and returns a list of all errors found. validate :: XmlFilter validate = validateDTD +++ validateDoc -- | -- Check if the DTD is valid. -- -- -- - returns : a function which expects an XmlTree from the parser as input -- and returns a list of all errors found in the DTD. validateDTD :: XmlFilter validateDTD = choice [ getDTDSubset :-> DTDValidation.validateDTD , this :-> err "Can't validate DTD: There is no DOCTYPE declaration in the document." ] -- | -- Check if the document corresponds to the given DTD. -- -- -- - returns : a function which expects a complete document as XmlTree input -- and returns a list of all errors found in the content part. validateDoc :: XmlFilter validateDoc t = ( if null dtds then err "Can't validate document: There is no DOCTYPE declaration in the document." else ( DocValidation.validateDoc dtdPart +++ IdValidation.validateIds dtdPart ) ) $ t where dtds = getDTDSubset .> processBottomUp removeDoublicateDefs $ t dtdPart = head dtds -- | -- filter for transforming a document with respect to the given DTD. -- -- Validating parsers -- are expected to normalize attribute values and add default values. -- This function should be called after a successful validation. -- -- -- - returns : a function which expects a complete XML document tree -- and returns the transformed XmlTree transform :: XmlFilter transform = choice [ isRoot :-> transformDoc , this :-> fatal "Can't transform document: No document root given" ] where transformDoc t | null dtds = this t | otherwise = DocTransformation.transform (head dtds) t where dtds = getDTDSubset .> processBottomUp removeDoublicateDefs $ t -- | -- Removes doublicate declarations from the DTD which first declaration is -- binding. This is the case for ATTLIST and ENTITY declarations. -- -- -- - returns : A function that replaces the children of DOCTYPE nodes by a list -- where all multiple declarations are removed. removeDoublicateDefs :: XmlFilter removeDoublicateDefs = DTDValidation.removeDoublicateDefs -- -- selects the DTD part of a document -- but only, if there is more than the internal part for the 4 predefined XML entities getDTDSubset :: XmlFilter getDTDSubset = getChildren .> isDoctype .> hasRootName where hasRootName = isOf (hasEntry a_name . attrlOfDTD)