+ parse_results = map read_either_int elements
+
+
+
+-- | Parse an optional 'Int' from a direct descendent of the
+-- (top-level) \<message\> element in an XmlTree. This is just like
+-- 'parse_message_int', except we expect the element/value to be
+-- missing sometimes.
+--
+-- To handle the fact that the element/value is optional, we pattern
+-- match on the 'ParseError' that comes back in case of failure. If
+-- we didn't find anything, we turn that into a \"successful
+-- nothing\". But if we find a value and it can't be parsed, we let
+-- the error propagate, because that shouldn't happen. Of course, if
+-- the parse worked, that's nice too: we wrap the parsed value in a
+-- 'Just' and return that wrapped in a 'Right'
+--
+parse_message_int_optional :: String
+ -> XmlTree
+ -> Either ParseError (Maybe Int)
+parse_message_int_optional child xmltree =
+ case (parse_message_int child xmltree) of
+ Left (ParseNotFound _) -> Right Nothing
+ Left pm@(ParseMismatch {}) -> Left pm
+ Right whatever -> Right (Just whatever)
+
+
+
+-- | Extract the \"XML_File_ID\" element from a document. If we fail
+-- to parse an XML_File_ID, we return an appropriate 'ParseError'
+-- wrapped in a 'Left' constructor. The reason should be one of two
+-- things:
+--
+-- 1. No XML_File_ID elements were found.
+--
+-- 2. An XML_File_ID element was found, but it could not be read
+-- into an Int.
+--
+-- In general we expect some non-integer XML_File_IDs, because they
+-- appear on the feed. But the htsn daemon refuses to save them at
+-- the moment, so if we ever see an XML_File_ID that we can't parse,
+-- it's truly an error.
+--
+parse_xmlfid :: XmlTree -> Either ParseError Int
+parse_xmlfid = parse_message_int "XML_File_ID"
+
+
+
+-- | Extract the \<game_id\> element from within the top-level
+-- \<message\> of a document. These appear in the "TSN.XML.GameInfo"
+-- documents. Unlike the \<XML_File_ID\> elements, the \<game_id\>
+-- can be missing from GameInfo documents, so for our implementation
+-- we use 'parse_message_int_optional' instead.
+--
+parse_game_id :: XmlTree -> Either ParseError (Maybe Int)
+parse_game_id = parse_message_int_optional "game_id"
+
+
+
+-- | Extract the \<schedule_id\> element from within the top-level
+-- \<message\> of a document. Identical to 'parse_game_id' except
+-- for the element name.
+--
+parse_schedule_id :: XmlTree -> Either ParseError (Maybe Int)
+parse_schedule_id = parse_message_int_optional "schedule_id"