+
+-- * NewsTeam
+
+-- | The database/XML type for teams as they show up in the news. We
+-- can't reuse the representation from "TSN.Team" because they
+-- require a team id. We wouldn't want to make the team ID optional
+-- and then insert a team with no id, only to find the same team
+-- later with an id and be unable to update the record. (We could
+-- add the update logic, but it would be more trouble than it's
+-- worth.)
+--
+data NewsTeam =
+ NewsTeam { team_name :: String }
+ deriving (Eq, Show)
+
+
+
+-- * News_NewsTeam
+
+-- | Mapping between News records and NewsTeam records in the
+-- database. We don't name the fields because we don't use the names
+-- explicitly; that means we have to give them nice database names
+-- via groundhog.
+--
+data News_NewsTeam = News_NewsTeam
+ (DefaultKey News)
+ (DefaultKey NewsTeam)
+
+
+-- * News_Location
+
+-- | Mapping between 'News' records and 'Location' records in the
+-- database. We don't name the fields because we don't use the names
+-- explicitly; that means we have to give them nice database names
+-- via groundhog.
+--
+data News_Location = News_Location
+ (DefaultKey News)
+ (DefaultKey Location)
+
+
+
+
+-- | Some newsxml documents contain two \<SMS\> elements in a row,
+-- violating the DTD. The second one has always been empty, but it's
+-- irrelevant: we can't parse these, and would like to detect them
+-- in order to report the fact that the busted document is
+-- unsupported.
+--
+-- This function detects whether two \<SMS\> elements appear in a
+-- row, as siblings.
+--
+has_only_single_sms :: XmlTree -> Bool
+has_only_single_sms xmltree =
+ case elements of
+ [] -> True
+ _ -> False
+ where
+ parse :: XmlTree -> [XmlTree]
+ parse = runLA $ hasName "/"
+ /> hasName "message"
+ >>> addNav
+ >>> descendantAxis
+ >>> filterAxis (hasName "SMS")
+ >>> followingSiblingAxis
+ >>> remNav
+ >>> hasName "SMS"
+
+ elements = parse xmltree
+
+
+--
+-- * Database code
+--
+