]> gitweb.michael.orlitzky.com - dead/htsn-import.git/blobdiff - src/Main.hs
Allow "TBA" laps in TSN.XML.AutoRacingSchedule.
[dead/htsn-import.git] / src / Main.hs
index 0682f8e112cb1537e424849cf227cee8bcaa5024..a2277057940edabe70df7517f250ed1f7d99649e 100644 (file)
@@ -22,6 +22,7 @@ import System.IO.Error ( catchIOError )
 import Text.XML.HXT.Core (
   ArrowXml,
   IOStateArrow,
+  SysConfigList,
   XmlTree,
   (>>>),
   (/>),
@@ -46,6 +47,9 @@ import Network.Services.TSN.Report (
   report_error )
 import TSN.DbImport ( DbImport(..), ImportResult(..) )
 import TSN.Parse ( format_parse_error )
+import qualified TSN.XML.AutoRacingDriverList as AutoRacingDriverList (
+  dtd,
+  pickle_message )
 import qualified TSN.XML.AutoRacingResults as AutoRacingResults (
   dtd,
   pickle_message )
@@ -80,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
@@ -106,9 +110,13 @@ import_file cfg path = do
   results <- parse_and_import `catch` exception_handler
   case results of
     []    -> do
-      -- One of the arrows returned "nothing."
-      report_error $ "Unable to determine DTD for file " ++ path ++ "."
-      return False
+      -- One of the arrows returned "nothing."  Now that we're
+      -- validating against the DTDs, this will almost always be
+      -- caused by a document whose DTD is not present (i.e. is
+      -- unsupported). So we return "success" to allow the XML file to
+      -- be deleted.
+      report_info $ "No DTD for file " ++ path ++ "."
+      return True
     (ImportFailed errmsg:_) -> do
       report_error $ errmsg ++ " (" ++ path ++ ")"
       return False
@@ -137,9 +145,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.
@@ -153,11 +163,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'.
@@ -195,6 +221,9 @@ import_file cfg path = do
                    (unpickleDoc f xml)
 
           importer
+            | dtd == AutoRacingDriverList.dtd =
+                go AutoRacingDriverList.pickle_message
+
             | dtd == AutoRacingResults.dtd =
                 go AutoRacingResults.pickle_message
 
@@ -211,8 +240,7 @@ import_file cfg path = do
 
             | dtd == JFile.dtd = go JFile.pickle_message
 
-            | dtd == MLBEarlyLine.dtd =
-                go MLBEarlyLine.pickle_message
+            | dtd == MLBEarlyLine.dtd = go MLBEarlyLine.pickle_message
 
             | dtd == News.dtd =
                 -- Some of the newsxml docs are busted in predictable ways.
@@ -265,6 +293,10 @@ import_file cfg path = do
             | otherwise = do
               let infomsg =
                     "Unrecognized DTD in " ++ path ++ ": " ++ dtd ++ "."
+              -- This should be an impossible case while DTD
+              -- validation is enabled. If we can parse the file at
+              -- all, then we have a DTD for it sitting around. And we
+              -- only have DTDs for supported types.
               return $ ImportUnsupported infomsg