import Text.XML.HXT.Core (
ArrowXml,
IOStateArrow,
+ SysConfigList,
XmlTree,
(>>>),
(/>),
is_type1,
pickle_message,
teams_are_normal )
-import Xml ( DtdName(..), parse_opts )
+import Xml ( DtdName(..), parse_opts, parse_opts_novalidate )
-- | This is where most of the work happens. This function is called
-- we couldn't parse the DTD.
return [ImportFailed errdesc]
- -- | An arrow that reads a document into an 'XmlTree'.
- readA :: IOStateArrow s a XmlTree
- readA = readDocument parse_opts path
+ -- | An arrow that reads a document into an 'XmlTree'. We take a
+ -- SysConfigList so our caller can decide whether or not to
+ -- e.g. validate the document against its DTD.
+ readA :: SysConfigList -> IOStateArrow s a XmlTree
+ readA scl = readDocument scl path
-- | An arrow which parses the doctype "SYSTEM" of an 'XmlTree'.
-- We use these to determine the parser to use.
-- The result of runX has type IO [IO ImportResult]. We thus use
-- bind (>>=) and sequence to combine all of the IOs into one
-- big one outside of the list.
+ --
+ -- Before we actually run the import, we check it against a list
+ -- of problem DTDs. These can produce weird errors, and we have
+ -- checks for them. But with DTD validation enabled, we can't
+ -- even look inside the document to see what's wrong -- parsing
+ -- will fail! So for those special document types, we proceed
+ -- using 'parse_opts_novalidate' instead of the default
+ -- 'parse_opts'.
+ --
parse_and_import :: IO [ImportResult]
- parse_and_import =
- runX (readA >>> (dtdnameA &&& returnA) >>> (arr import_with_dtd))
- >>=
- sequence
+ parse_and_import = do
+ -- Get the DTD name without validating against it.
+ ((DtdName dtd) : _) <- runX $ (readA parse_opts_novalidate) >>> dtdnameA
+
+ let problem_dtds = [ News.dtd, Weather.dtd ]
+ let opts = if dtd `elem` problem_dtds
+ then parse_opts_novalidate
+ else parse_opts
+
+ runX ((readA opts) >>> (dtdnameA &&& returnA) >>> (arr import_with_dtd))
+ >>= sequence
-- | Takes a ('DtdName', 'XmlTree') pair and uses the 'DtdName'
-- to determine which function to call on the 'XmlTree'.