UweSchmidt / hxt

Haskell XML Toolbox
http://www.fh-wedel.de/~si/HXmlToolbox/index.html
124 stars 34 forks source link

Example of an unpickling that works only when DTD validation is enabled. #16

Closed orlitzky closed 10 years ago

orlitzky commented 10 years ago

I found this rather strange:

https://gist.github.com/mjorlitzky/8431680

There is a bug in my unpickling code; the line,

(xpAttrImplied "name" xpText)

should instead be,

(xpAttr "name" $ xpOption xpText)

since it is the attribute text and not the attribute itself that is optional. But even so, the former translates into,

xpOption $ xpAttr "name" xpText

which in my current state of unsleep does nothing to explain the following:

$ runghc Main.hs 
[Message {xml_xml_file_id = 19996383, xml_heading = "AFW%COLLFBWEATHER", xml_category = "Weather", xml_sport = "CFOOT", xml_title = "College Football Weather Forecast", xml_forecasts = [WeatherForecastXml {xml_game_date = "Monday, December 30th", xml_league = WeatherLeague {league_name = Just "", listings = [WeatherListing {db_teams = "Middle Tennessee at Navy, 11:45 a.m.", db_weather = "Mostly sunny. Winds northwest at 5-10 m.p.h. (Fort Worth, TX)  Game-time temperature: Around 35."},WeatherListing {db_teams = "Ole Miss at Georgia Tech, 3:15 p.m.", db_weather = "Partly cloudy. Winds northwest at 1-10 m.p.h. (Nashville, TN)  Game-time temperature: Near 40."},WeatherListing {db_teams = "Oregon at Texas, 6:45 p.m.", db_weather = "Game is being played inside a dome. (San Antonio, TX)"},WeatherListing {db_teams = "Arizona State at Texas Tech, 10:15 p.m.", db_weather = "Clear. Winds northeast at 1-5 m.p.h. (San Diego, CA)  Game-time temperature: Around 60."}]}},WeatherForecastXml {xml_game_date = "Tuesday, December 31st", xml_league = WeatherLeague {league_name = Just "", listings = [WeatherListing {db_teams = "Arizona at Boston College, 12:30 p.m.", db_weather = "Mostly sunny. Winds southeast at 1-5 m.p.h. (Shreveport, LA)  Game-time temperature: Around 50."},WeatherListing {db_teams = "Virginia Tech at UCLA, 2:10 p.m.", db_weather = "Sunny. Winds southwest at 1-5 m.p.h. (El Paso, TX)  Game-time temperature: Around 55."},WeatherListing {db_teams = "Rice at Miss State, 4:00 p.m.", db_weather = "Sunny. Winds southwest at 1-10 m.p.h. (Memphis, TN)  Game-time temperature: Around 45."},WeatherListing {db_teams = "Duke at Texas A&M, 8:00 p.m.", db_weather = "Game is being played inside a dome. (Atlanta, GA)"}]}}], xml_time_stamp = " December 30, 2013, at 09:10 AM ET "}]

fatal error: document unpickling failed
xpCheckEmptyAttributes: unprocessed XML attribute(s) detected
context:    element "league"
attributes:  name=""
UweSchmidt commented 10 years ago

here is a change in the pickler for league, that works with validation and without. xpText0 accepts empty string (xpText does not) and the empty string is mapped to a maybe value.

pickle_league :: PU WeatherLeague
 pickle_league =
  xpElem "league" $
    xpWrap (from_pair, to_pair) $
      xpPair
        (xpAttr "name" $
                xpWrap (\ x -> if null x then Nothing else Just x
                       , fromMaybe ""
                       ) xpText0
        )
        (xpList pickle_listing)
  where
    from_pair = uncurry WeatherLeague
    to_pair WeatherLeague{..} = (league_name, listings)

The whole code becomes simpler if League is defined without Maybe

data WeatherLeague =
  WeatherLeague {
    league_name     :: String,
    listings :: [WeatherListing] }
  deriving (Eq, Show)

In that case the pickler becomes

xpAttr "name" xpText0

At the moment I don't have any idea, why the pickler behaved different for validated and not validated documents. I could reproduce the error, but I have not seen any differences in the XML trees. I will have a look into that. I hope you can live with that workaround.

Cheer, Uwe

orlitzky commented 10 years ago

Yeah I've worked around it for now. I almost ate my monitor when I figured out that "withValidate no" was making it fail to unpickle though =P