@@ -9,6 +9,7 @@ import Data.Text (Text)
9import qualified Data.Text as Text
9import qualified Data.Text as Text
10import qualified Data.Text.IO as Text
10import qualified Data.Text.IO as Text
11import Data.Maybe
11import Data.Maybe
12+import qualified Data.List as List
12import qualified Data.Set as Set
13import qualified Data.Set as Set
13import Data.Map (Map)
14import Data.Map (Map)
14import qualified Data.Map as Map
15import qualified Data.Map as Map
@@ -37,21 +38,27 @@ data Result = Result
38generate :: Options -> Xsd.Schema -> Either String Result
39generate :: Options -> Xsd.Schema -> Either String Result
39generate opts schema = do
40generate opts schema = do
42+ types = Map.union (Xsd.schemaTypes schema)
43+ (elementsToTypes (Xsd.schemaElements schema))
40− s <- runGen (initialGenState opts schema) $ do
44+ s <- runGen (initialGenState opts types) $ do
41 genHeader opts
45 genHeader opts
42− genTypes (Xsd.schemaTypes schema)
46+ genTypes types
43− genElements (Xsd.schemaElements schema)
44 Right Result
47 Right Result
45 { resultCode = Text.unlines (reverse (gsCode s))
48 { resultCode = Text.unlines (reverse (gsCode s))
46 , resultWarnings = reverse (gsWarnings s)
49 , resultWarnings = reverse (gsWarnings s)
52+elementsToTypes :: Map Xsd.QName Xsd.Element -> Map Xsd.QName Xsd.Type
53+elementsToTypes = List.foldl' step Map.empty . Map.toList
55+ step types (_, e) = case Xsd.elementType e of
57+ Xsd.Inline t -> Map.insert (Xsd.elementName e) t types
49genTypes :: Map Xsd.QName Xsd.Type -> Gen ()
59genTypes :: Map Xsd.QName Xsd.Type -> Gen ()
50genTypes types = mapM_ (uncurry genTopType) . Map.toList $ types
60genTypes types = mapM_ (uncurry genTopType) . Map.toList $ types
52−genElements :: Map Xsd.QName Xsd.Element -> Gen ()
53−genElements = mapM_ genElement
55genTopType :: Xsd.QName -> Xsd.Type -> Gen ()
62genTopType :: Xsd.QName -> Xsd.Type -> Gen ()
56genTopType = genType []
63genTopType = genType []
@@ -69,6 +76,105 @@ genType annotations name tp = do
69 case tp of
76 case tp of
70 Xsd.TypeSimple t -> genSimpleType typeName t annotations
77 Xsd.TypeSimple t -> genSimpleType typeName t annotations
71 Xsd.TypeComplex t -> genComplexType typeName t annotations
78 Xsd.TypeComplex t -> genComplexType typeName t annotations
81+genExtension :: Xsd.QName -> Gen ()
82+genExtension base = do
83+ exts <- extensions base
87+ mapM_ (uncurry genTopType) types
88+ baseTypeName <- tnPrefixed <$> resolveTypeName base
90+ [ "data Any" <> baseTypeName
91+ , " = The" <> baseTypeName <> " !" <> baseTypeName
94+ mkConstructor (n, _) = do
95+ tn <- tnPrefixed <$> resolveTypeName n
96+ exts' <- extensions n
101+ return (" | The" <> n' <> " !" <> n')
102+ constructors <- mapM mkConstructor types
103+ writeCode constructors
105+ [ " deriving (Eq, Show)"
109+ [ "instance NFData Any" <> baseTypeName <> " where"
114+ unless (mode == Generator) $ do
116+ [ "instance FromDom Any" <> baseTypeName <> " where"
118+ , " tp <- parseAttribute"
120+ "\"{http://www.w3.org/2001/XMLSchema-instance}type\")"
126+ tn <- resolveTypeName n
127+ exts' <- extensions n
129+ [] -> return (tnPrefixed tn)
130+ _ | n == base -> return (tnPrefixed tn)
131+ _ -> return ("Any" <> tnPrefixed tn)
139+ clauses <- mapM mkClause (base : map fst types)
142+ unless (mode == Parser) $ do
144+ [ "instance ToXML Any" <> baseTypeName <> " where"
145+ , " toXML (The" <> baseTypeName <> " a) = toXML a"
148+ mkClause (n, _) = do
149+ tn <- tnPrefixed <$> resolveTypeName n
150+ exts' <- extensions n
155+ return (" toXML (The" <> n' <> " a) = toXML a")
156+ clauses <- mapM mkClause types
160+ [ "instance ToXmlParentAttributes Any" <> baseTypeName <> " where"
164+ tn <- resolveTypeName n
165+ exts' <- extensions n
167+ [] -> return (tnPrefixed tn)
168+ _ | n == base -> return (tnPrefixed tn)
169+ _ -> return ("Any" <> tnPrefixed tn)
171+ [ " toXmlParentAttributes (The" <> n' <> " a) ="
172+ , " (\"{http://www.w3.org/2001/XMLSchema-instance}type\", \""
173+ <> tnName tn <> "\")"
174+ , " : toXmlParentAttributes a"
176+ attrLines <- mapM toAttrLine (base : map fst types)
177+ writeCode (concat attrLines)
73genDependencies :: References a => a -> Gen ()
179genDependencies :: References a => a -> Gen ()
74genDependencies a = forM_ (references a) $ \name -> do
180genDependencies a = forM_ (references a) $ \name -> do
@@ -97,7 +203,7 @@ genSimpleType typeName (Xsd.ListType _ _) _ = genUnsupported typeName
98genNewtype :: TypeName -> Xsd.QName -> [Xsd.Annotation] -> Gen ()
204genNewtype :: TypeName -> Xsd.QName -> [Xsd.Annotation] -> Gen ()
99genNewtype tn base annots = do
205genNewtype tn base annots = do
100− fieldTypeName <- resolveTypeName base
206+ fieldTypeName <- tnPrefixed <$> resolveTypeName base
101 mode <- getMode
207 mode <- getMode
103 typeName = tnPrefixed tn
209 typeName = tnPrefixed tn
@@ -143,7 +249,7 @@ genComplexType typeName t parentAnn = do
144 header = "\"" <> tnName typeName <> "\" =:= record "
250 header = "\"" <> tnName typeName <> "\" =:= record "
145 <> genTypeToText mode
251 <> genTypeToText mode
146− fields <- maybe (return []) (genFields typeName) (Xsd.complexModelGroup t)
252+ fields <- genFields typeName (Xsd.complexContent t)
147 writeCode $ makeComments typeName
253 writeCode $ makeComments typeName
148 (parentAnn <> Xsd.complexAnnotations t)
254 (parentAnn <> Xsd.complexAnnotations t)
149 writeCode [header]
255 writeCode [header]
@@ -168,13 +274,28 @@ makeComments typeName annotations =
168-- | Generate code for record fields
274-- | Generate code for record fields
170-- The first argument - record name
276-- The first argument - record name
171−genFields :: TypeName -> Xsd.ModelGroup -> Gen [Text]
277+genFields :: TypeName -> Xsd.Content -> Gen [Text]
278+genFields typeName (Xsd.ContentPlain c) =
279+ maybe (return []) (genFieldsForModel typeName) (Xsd.plainContentModel c)
280+genFields _ (Xsd.ContentSimple _) = return []
281+genFields typeName (Xsd.ContentComplex (Xsd.ComplexContentExtension e)) = do
282+ base <- resolveType (Xsd.complexExtensionBase e)
283+ baseFields <- case base of
284+ Xsd.TypeComplex t -> genFields typeName (Xsd.complexContent t)
286+ fields <- maybe (return []) (genFieldsForModel typeName)
287+ (Xsd.complexExtensionModel e)
288+ return (baseFields ++ fields)
289+genFields _ (Xsd.ContentComplex Xsd.ComplexContentRestriction) =
292+genFieldsForModel :: TypeName -> Xsd.ModelGroup -> Gen [Text]
172−genFields typeName (Xsd.Sequence elements) =
293+genFieldsForModel typeName (Xsd.Sequence elements) =
173 catMaybes <$> mapM (genField typeName) elements
294 catMaybes <$> mapM (genField typeName) elements
174−genFields _ (Xsd.Choice _) = do
295+genFieldsForModel _ (Xsd.Choice _) = do
175 warn "choice: not implemented"
296 warn "choice: not implemented"
176 return []
297 return []
177−genFields _ (Xsd.All _) = do
298+genFieldsForModel _ (Xsd.All _) = do
178 warn "all: not implemented"
299 warn "all: not implemented"
179 return []
300 return []
@@ -183,10 +304,15 @@ genField typeName e = do
183 fieldName <- makeFieldName typeName (Xsd.elementName e)
304 fieldName <- makeFieldName typeName (Xsd.elementName e)
185 fieldTypeName <- case Xsd.elementType e of
306 fieldTypeName <- case Xsd.elementType e of
186− Xsd.Ref name -> resolveTypeName name
308+ tn <- tnPrefixed <$> resolveTypeName name
309+ exts <- extensions name
312+ _ -> return ("Any" <> tn)
187 Xsd.Inline t -> do
313 Xsd.Inline t -> do
188 genType (Xsd.elementAnnotations e) (Xsd.elementName e) t
314 genType (Xsd.elementAnnotations e) (Xsd.elementName e) t
189− resolveTypeName (Xsd.elementName e)
315+ tnPrefixed <$> resolveTypeName (Xsd.elementName e)
191 qualifier <- makeQualifier (Xsd.elementOccurs e)
317 qualifier <- makeQualifier (Xsd.elementOccurs e)
@@ -243,11 +369,6 @@ genUnsupported tn = do
246−genElement :: Xsd.Element -> Gen ()
247−genElement e = case Xsd.elementType e of
248− Xsd.Ref _ -> return ()
249− Xsd.Inline t -> genType (Xsd.elementAnnotations e) (Xsd.elementName e) t
251genHeader :: Options -> Gen ()
372genHeader :: Options -> Gen ()
252genHeader opts = do
373genHeader opts = do
253 case oHeader opts of
374 case oHeader opts of
@@ -270,17 +391,19 @@ genHeader opts = do
272 imports = case oMode opts of
393 imports = case oMode opts of
273− Generator -> [ xmlWriter ]
394+ Generator -> [ xmlWriter, parentAttr ]
274 Parser -> [ domParser ]
395 Parser -> [ domParser ]
275− Both -> [ domParser, xmlWriter ]
396+ Both -> [ domParser, xmlWriter, parentAttr ]
276− xmlWriter = "import Text.XML.Writer"
397+ xmlWriter = "import Text.XML.Writer"
277− domParser = "import Text.XML.DOM.Parser.FromDom"
398+ parentAttr = "import Text.XML.ParentAttributes"
399+ domParser = "import Text.XML.DOM.Parser"
279-- | We populate the initial state with all built-in types to make sure
401-- | We populate the initial state with all built-in types to make sure
280-- they will be correctly resolved
402-- they will be correctly resolved
281−initialGenState :: Options -> Xsd.Schema -> GenState
403+initialGenState :: Options -> Map Xsd.QName Xsd.Type -> GenState
282−initialGenState opts schema = GenState
404+initialGenState opts types = GenState
283− { gsTypes = Xsd.schemaTypes schema
405+ { gsTypes = types
406+ , gsExtensions = collectExtensions types
284 , gsKnownTypes = builtInTypes
407 , gsKnownTypes = builtInTypes
285 , gsBoundTypeName = Set.empty
408 , gsBoundTypeName = Set.empty
286 , gsBoundFields = Set.empty
409 , gsBoundFields = Set.empty
@@ -288,3 +411,17 @@ initialGenState opts schema = GenState
288 , gsCode = []
411 , gsCode = []
289 , gsWarnings = []
412 , gsWarnings = []
416+ :: Map Xsd.QName Xsd.Type
417+ -> Map Xsd.QName [(Xsd.QName, Xsd.Type)]
418+collectExtensions = List.foldl' step Map.empty . Map.toList
420+ step exts (n, t) = case baseOf t of
422+ Just base -> Map.insertWith (++) base [(n, t)] exts
423+ baseOf (Xsd.TypeSimple _) = Nothing
424+ baseOf (Xsd.TypeComplex t) = case Xsd.complexContent t of
425+ Xsd.ContentComplex (Xsd.ComplexContentExtension e) ->
426+ Just (Xsd.complexExtensionBase e)