deriveXmlEnum :: Options -> Name -> DecsQ
deriveXmlEnum opts name = withType name $ \name tvbs cons -> do
  let doExpr :: (XmlName, ConName) -> Q Exp
      doExpr (xmlName, conName) = [| do literal $(return $ LitE $ StringL xmlName) ; return $(return $ ConE $ mkName conName) |]
      conInfo :: Con -> (XmlName, ConName)
      conInfo con = let cn = showName $ conName con in (constructorTagModifier opts cn, cn)
      nameInfos :: [(XmlName, ConName)]
      nameInfos = map conInfo cons
      acceptingParserBody :: ExpQ
      acceptingParserBody = joinExprs (map doExpr nameInfos) (return $ VarE $ mkName "onFail")
      nameInfoClause :: (XmlName, ConName) -> Clause
      nameInfoClause (xmlName, conName) = Clause [ConP (mkName conName) []] (NormalB $ LitE $ StringL xmlName) []
      simpleTypeTextDec :: Dec
      simpleTypeTextDec = FunD (mkName "simpleTypeText") (map nameInfoClause nameInfos)
      simpleTypeInstanceDec :: Q Dec
      simpleTypeInstanceDec = do
        acceptingParserB <- acceptingParserBody
        let acceptingParserDec = FunD (mkName "acceptingParser") [Clause [] (NormalB $ acceptingParserB) []]
        return $ InstanceD [] (AppT (ConT ''SimpleType) $ ConT name) [
          acceptingParserDec,
          simpleTypeTextDec
          ]
  
      schemaTypeInstanceDec = [d|
        instance SchemaType $(return $ ConT name) where
          parseSchemaType s = do
            e <- element [s]
            commit $ interior e $ parseSimpleType
          schemaTypeToXML s x =
            toXMLElement s [] [toXMLText (simpleTypeText x)]
        |]
  (++) <$> schemaTypeInstanceDec <*> (pure <$> simpleTypeInstanceDec)
deriveXmlEnum :: Options -> Name -> DecsQ
deriveXmlEnum opts name = withType name $ \name tvbs cons -> do
  let doExpr :: (XmlName, ConName) -> Q Exp
      doExpr (xmlName, conName) = [| do literal $(return $ LitE $ StringL xmlName) ; return $(return $ ConE $ mkName conName) |]
      conInfo :: Con -> (XmlName, ConName)
      conInfo con = let cn = showName $ conName con in (constructorTagModifier opts cn, cn)
      nameInfos :: [(XmlName, ConName)]
      nameInfos = map conInfo cons
      acceptingParserBody :: ExpQ
      acceptingParserBody = joinExprs (map doExpr nameInfos) (return $ VarE $ mkName "onFail")
      nameInfoClause :: (XmlName, ConName) -> Clause
      nameInfoClause (xmlName, conName) = Clause [ConP (mkName conName) []] (NormalB $ LitE $ StringL xmlName) []
      simpleTypeTextDec :: Dec
      simpleTypeTextDec = FunD (mkName "simpleTypeText") (map nameInfoClause nameInfos)
      simpleTypeInstanceDec :: Q Dec
      simpleTypeInstanceDec = do
        acceptingParserB <- acceptingParserBody
        let acceptingParserDec = FunD (mkName "acceptingParser") [Clause [] (NormalB $ acceptingParserB) []]
        return $ InstanceD [] (AppT (ConT ''SimpleType) $ ConT name) [
          acceptingParserDec,
          simpleTypeTextDec
          ]
  
      schemaTypeInstanceDec = [d|
        instance SchemaType $(return $ ConT name) where
          parseSchemaType s = do
            e <- element [s]
            commit $ interior e $ parseSimpleType
          schemaTypeToXML s x =
            toXMLElement s [] [toXMLText (simpleTypeText x)]
        |]
  (++) <$> schemaTypeInstanceDec <*> (pure <$> simpleTypeInstanceDec)
deriveXmlEnum opts name = withType name $ \name tvbs cons -> do
  let doExpr :: (XmlName, ConName) -> Q Exp
      doExpr (xmlName, conName) = [| do literal $(return $ LitE $ StringL xmlName) ; return $(return $ ConE $ mkName conName) |]
      conInfo :: Con -> (XmlName, ConName)
      conInfo con = let cn = showName $ conName con in (constructorTagModifier opts cn, cn)
      nameInfos :: [(XmlName, ConName)]
      nameInfos = map conInfo cons
      acceptingParserBody :: ExpQ
      acceptingParserBody = joinExprs (map doExpr nameInfos) (return $ VarE $ mkName "onFail")
      nameInfoClause :: (XmlName, ConName) -> Clause
      nameInfoClause (xmlName, conName) = Clause [ConP (mkName conName) []] (NormalB $ LitE $ StringL xmlName) []
      simpleTypeTextDec :: Dec
      simpleTypeTextDec = FunD (mkName "simpleTypeText") (map nameInfoClause nameInfos)
      simpleTypeInstanceDec :: Q Dec
      simpleTypeInstanceDec = do
        acceptingParserB <- acceptingParserBody
        let acceptingParserDec = FunD (mkName "acceptingParser") [Clause [] (NormalB $ acceptingParserB) []]
        return $ InstanceD [] (AppT (ConT ''SimpleType) $ ConT name) [
          acceptingParserDec,
          simpleTypeTextDec
          ]
  
      schemaTypeInstanceDec = [d|
        instance SchemaType $(return $ ConT name) where
          parseSchemaType s = do
            e <- element [s]
            commit $ interior e $ parseSimpleType
          schemaTypeToXML s x =
            toXMLElement s [] [toXMLText (simpleTypeText x)]
        |]
  (++) <$> schemaTypeInstanceDec <*> (pure <$> simpleTypeInstanceDec)