]> gitweb.michael.orlitzky.com - dead/htsn-import.git/commitdiff
Use parse_opts_novalidate for the problem DTDs weatherxml and newsxml.
authorMichael Orlitzky <michael@orlitzky.com>
Sat, 24 Jan 2015 21:46:05 +0000 (16:46 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Sat, 24 Jan 2015 21:46:05 +0000 (16:46 -0500)
src/Main.hs

index a47c669b3544871e0e6bc1413db767fba6bacf66..e36cc789b4d2f2dbfa485e9af9326a2e63da4824 100644 (file)
@@ -22,6 +22,7 @@ import System.IO.Error ( catchIOError )
 import Text.XML.HXT.Core (
   ArrowXml,
   IOStateArrow,
+  SysConfigList,
   XmlTree,
   (>>>),
   (/>),
@@ -83,7 +84,7 @@ import qualified TSN.XML.Weather as Weather (
   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
@@ -140,9 +141,11 @@ import_file cfg path = do
       -- 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.
@@ -156,11 +159,27 @@ import_file cfg path = do
     --   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'.