git.iko.soy/typeable/xsd-isogen
on 5877fd2 help sign in
35 files changed+417−1682
since splitsnapshots
unifiedsplit
README.md+7−18 cabal.project+2−2 golden/README−3 golden/ambig.xsd−20 golden/ambig.xsd.hs−39 golden/ambig1.xsd−16 golden/ambig1.xsd.hs−39 golden/enum.xsd−12 golden/enum.xsd.hs−25 golden/extension.xsd−36 golden/extension.xsd.hs−83 golden/extension_dep.xsd−31 golden/extension_dep.xsd.hs−101 golden/import.xsd−16 golden/import.xsd.hs−33 golden/import_ambig.xsd−26 golden/import_ambig.xsd.hs−50 golden/imported.xsd−9 golden/imported.xsd.hs−27 golden/include.xsd−5 golden/include.xsd.hs−27 golden/included.xsd−6 golden/included.xsd.hs−27 golden/seq.xsd−14 golden/seq.xsd.hs−34 golden/simple.xsd−25 golden/simple.xsd.hs−40 golden/test.sh−5 src/BuiltInTypes.hs−67 src/Gen.hs−213 src/Main.hs+395−438 src/Options.hs−84 src/References.hs−80 stack.yaml−12 xsd-isogen.cabal+13−19
README.md+7−18
@@ -5,24 +5,13 @@ Tool to generate xml-isogen descriptions from xsd files
55Usage
66=====
77
8−Use `xsd-isogen -i in.xsd -m Generator > out.hs` for queries.
8+Use `xsd-isogen in.xsd Generator > out.hs` for queries.
99
10−Use `xsd-isogen -i in.xsd -m Parser > out.hs` for responses.
10+Use `xsd-isogen in.xsd Parser > out.hs` for responses.
1111
12−Use `xsd-isogen -i in.xsd -m Both > out.hs` for common definitions.
12+Use `xsd-isogen in.xsd Both > out.hs` for common definitions.
1313
14−If there are conflicting field names in some datatypes, one of the the datatype names gets consecutive numbers starting from 2 appended to it (so that the field name prefix changes) until there are no more conflicts.
15−
16−## Available options:
17− - `--no-header`:
18− Do not place a header at the top of the file.
19− - `--header ARG`:
20− A custom header to be placed at the top of the file.
21− - `-m,--mode ARG`:
22− Whether to generate both parsers and generators. One of: Parser, Generator, Both.
23− - `-i,--input ARG`:
24− Path to the input .xsd file.
25− - `-n,--name ARG`:
26− Specify the name of the generated module.
27− - `-h,--help`:
28− Show this help text
14+Keep in mind that name clashes are possible and should be disambiguated
15+manually. If you have a good idea how to handle that, feel free to create an
16+issue and/or PR. Module name for all auto-generated files is set to `module
17+Dummy where`, so it should be updated appropriately as well.
cabal.project+2−2
@@ -2,5 +2,5 @@ packages: .
22
33source-repository-package
44 type: git
5− location: https://github.com/typeable/xsd-parser.git
6− tag: e08a37cf08674a492407b9b7f4a61e8faedb1590
5+ location: https://github.com/dredozubov/xsd-parser.git
6+ tag: f9cbe65a9b9c37e9015a73707f1cd4f00e79c96e
golden/READMEdeleted−3
@@ -1,3 +0,0 @@
1−To use the golden tests, cd to this folder and run test.sh. It will run
2−xsd-isogen on each xsd file here. Then use git diff to check the
3−difference.
golden/ambig.xsddeleted−20
@@ -1,20 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:simpleType name="stringtype">
4− <xs:restriction base="xs:string"/>
5− </xs:simpleType>
6− <xs:element name="Aa">
7− <xs:complexType>
8− <xs:sequence>
9− <xs:element name="firstName" type="stringtype"/>
10− </xs:sequence>
11− </xs:complexType>
12− </xs:element>
13− <xs:element name="Ab">
14− <xs:complexType>
15− <xs:sequence>
16− <xs:element name="firstName" type="stringtype"/>
17− </xs:sequence>
18− </xs:complexType>
19− </xs:element>
20−</xs:schema>
golden/ambig.xsd.hsdeleted−39
@@ -1,39 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: stringtype
18−-}
19−newtype XmlStringtype
20− = XmlStringtype
21− { unXmlStringtype :: Text
22− } deriving (Show, Eq, NFData, ToXML)
23−
24−instance FromDom XmlStringtype where
25− fromDom = XmlStringtype <$> fromDom
26−
27−{-|
28−Generated from: Aa
29−-}
30−"Aa" =:= record ParserAndGenerator
31− ! "firstName" [t|XmlStringtype|]
32−
33−{-|
34−Generated from: Ab
35−-}
36−"Ab1" =:= record ParserAndGenerator
37− ! "firstName" [t|XmlStringtype|]
38−
39−
golden/ambig1.xsddeleted−16
@@ -1,16 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:simpleType name="stringtype">
4− <xs:restriction base="xs:string"/>
5− </xs:simpleType>
6− <xs:complexType name="Aa">
7− <xs:sequence>
8− <xs:element name="firstName" type="stringtype"/>
9− </xs:sequence>
10− </xs:complexType>
11− <xs:complexType name="Ab">
12− <xs:sequence>
13− <xs:element name="firstName" type="stringtype"/>
14− </xs:sequence>
15− </xs:complexType>
16−</xs:schema>
golden/ambig1.xsd.hsdeleted−39
@@ -1,39 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: stringtype
18−-}
19−newtype XmlStringtype
20− = XmlStringtype
21− { unXmlStringtype :: Text
22− } deriving (Show, Eq, NFData, ToXML)
23−
24−instance FromDom XmlStringtype where
25− fromDom = XmlStringtype <$> fromDom
26−
27−{-|
28−Generated from: Aa
29−-}
30−"Aa" =:= record ParserAndGenerator
31− ! "firstName" [t|XmlStringtype|]
32−
33−{-|
34−Generated from: Ab
35−-}
36−"Ab1" =:= record ParserAndGenerator
37− ! "firstName" [t|XmlStringtype|]
38−
39−
golden/enum.xsddeleted−12
@@ -1,12 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:simpleType name="stringtype">
4− <xs:annotation>
5− <xs:documentation>Blah</xs:documentation>
6− </xs:annotation>
7− <xs:restriction base="xs:string">
8− <xs:enumeration value="day"/>
9− <xs:enumeration value="night"/>
10− </xs:restriction>
11− </xs:simpleType>
12−</xs:schema>
golden/enum.xsd.hsdeleted−25
@@ -1,25 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: stringtype
18−
19−Blah
20−-}
21−"Stringtype" Exhaustive =:= enum ParserAndGenerator
22− & "Day"
23− & "Night"
24−
25−
golden/extension.xsddeleted−36
@@ -1,36 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:complexType name="some">
4− <xs:sequence>
5− <xs:element name="a" type="xs:string"/>
6− </xs:sequence>
7− </xs:complexType>
8− <xs:complexType name="basetype">
9− <xs:sequence>
10− <xs:element name="a" type="xs:string"/>
11− </xs:sequence>
12− </xs:complexType>
13− <xs:complexType name="ext1">
14− <xs:complexContent>
15− <xs:extension base="basetype">
16− <xs:sequence>
17− <xs:element name="b" type="xs:int"/>
18− </xs:sequence>
19− </xs:extension>
20− </xs:complexContent>
21− </xs:complexType>
22− <xs:complexType name="ext2">
23− <xs:complexContent>
24− <xs:extension base="basetype">
25− <xs:sequence>
26− <xs:element name="c" type="xs:int"/>
27− </xs:sequence>
28− </xs:extension>
29− </xs:complexContent>
30− </xs:complexType>
31− <xs:complexType name="other">
32− <xs:sequence>
33− <xs:element name="a" type="basetype"/>
34− </xs:sequence>
35− </xs:complexType>
36−</xs:schema>
golden/extension.xsd.hsdeleted−83
@@ -1,83 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: basetype
18−-}
19−"Basetype" =:= record ParserAndGenerator
20− ! "a" [t|Text|]
21−
22−{-|
23−Generated from: ext2
24−-}
25−"Ext2" =:= record ParserAndGenerator
26− ! "a" [t|Text|]
27− ! "c" [t|Integer|]
28−
29−{-|
30−Generated from: ext1
31−-}
32−"Ext1" =:= record ParserAndGenerator
33− ! "a" [t|Text|]
34− ! "b" [t|Integer|]
35−
36−data AnyXmlBasetype
37− = TheXmlBasetype !XmlBasetype
38− | TheXmlExt2 !XmlExt2
39− | TheXmlExt1 !XmlExt1
40− deriving (Eq, Show)
41−
42−instance NFData AnyXmlBasetype where
43− rnf = rwhnf
44−
45−instance FromDom AnyXmlBasetype where
46− fromDom = do
47− tp <- parseAttribute
48− (matchName "{http://www.w3.org/2001/XMLSchema-instance}type")
49− Right
50− case tp of
51− "Basetype" -> TheXmlBasetype <$> fromDom
52− "Ext2" -> TheXmlExt2 <$> fromDom
53− "Ext1" -> TheXmlExt1 <$> fromDom
54− _ -> throwParserError (PEOther "Unexpected type")
55−
56−instance ToXML AnyXmlBasetype where
57− toXML (TheXmlBasetype a) = toXML a
58− toXML (TheXmlExt2 a) = toXML a
59− toXML (TheXmlExt1 a) = toXML a
60−
61−instance ToXmlParentAttributes AnyXmlBasetype where
62− toXmlParentAttributes (TheXmlBasetype a) =
63− ("{http://www.w3.org/2001/XMLSchema-instance}type", "Basetype")
64− : toXmlParentAttributes a
65− toXmlParentAttributes (TheXmlExt2 a) =
66− ("{http://www.w3.org/2001/XMLSchema-instance}type", "Ext2")
67− : toXmlParentAttributes a
68− toXmlParentAttributes (TheXmlExt1 a) =
69− ("{http://www.w3.org/2001/XMLSchema-instance}type", "Ext1")
70− : toXmlParentAttributes a
71−{-|
72−Generated from: other
73−-}
74−"Other" =:= record ParserAndGenerator
75− ! "a" [t|AnyXmlBasetype|]
76−
77−{-|
78−Generated from: some
79−-}
80−"Some" =:= record ParserAndGenerator
81− ! "a" [t|Text|]
82−
83−
golden/extension_dep.xsddeleted−31
@@ -1,31 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:complexType name="X">
4− <xs:sequence>
5− <xs:element name="s" type="xs:string"/>
6− </xs:sequence>
7− </xs:complexType>
8− <xs:complexType name="B">
9− <xs:sequence>
10− <xs:element name="s" type="xs:string"/>
11− </xs:sequence>
12− </xs:complexType>
13− <xs:complexType name="C">
14− <xs:complexContent>
15− <xs:extension base="B">
16− <xs:sequence>
17− <xs:element name="x" type="X"/>
18− </xs:sequence>
19− </xs:extension>
20− </xs:complexContent>
21− </xs:complexType>
22− <xs:complexType name="A">
23− <xs:complexContent>
24− <xs:extension base="C">
25− <xs:sequence>
26− <xs:element name="i" type="xs:int"/>
27− </xs:sequence>
28− </xs:extension>
29− </xs:complexContent>
30− </xs:complexType>
31−</xs:schema>
golden/extension_dep.xsd.hsdeleted−101
@@ -1,101 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: X
18−-}
19−"X" =:= record ParserAndGenerator
20− ! "s" [t|Text|]
21−
22−{-|
23−Generated from: A
24−-}
25−"A" =:= record ParserAndGenerator
26− ! "s" [t|Text|]
27− ! "x" [t|XmlX|]
28− ! "i" [t|Integer|]
29−
30−{-|
31−Generated from: B
32−-}
33−"B" =:= record ParserAndGenerator
34− ! "s" [t|Text|]
35−
36−{-|
37−Generated from: C
38−-}
39−"C" =:= record ParserAndGenerator
40− ! "s" [t|Text|]
41− ! "x" [t|XmlX|]
42−
43−data AnyXmlC
44− = TheXmlC !XmlC
45− | TheXmlA !XmlA
46− deriving (Eq, Show)
47−
48−instance NFData AnyXmlC where
49− rnf = rwhnf
50−
51−instance FromDom AnyXmlC where
52− fromDom = do
53− tp <- parseAttribute
54− (matchName "{http://www.w3.org/2001/XMLSchema-instance}type")
55− Right
56− case tp of
57− "C" -> TheXmlC <$> fromDom
58− "A" -> TheXmlA <$> fromDom
59− _ -> throwParserError (PEOther "Unexpected type")
60−
61−instance ToXML AnyXmlC where
62− toXML (TheXmlC a) = toXML a
63− toXML (TheXmlA a) = toXML a
64−
65−instance ToXmlParentAttributes AnyXmlC where
66− toXmlParentAttributes (TheXmlC a) =
67− ("{http://www.w3.org/2001/XMLSchema-instance}type", "C")
68− : toXmlParentAttributes a
69− toXmlParentAttributes (TheXmlA a) =
70− ("{http://www.w3.org/2001/XMLSchema-instance}type", "A")
71− : toXmlParentAttributes a
72−data AnyXmlB
73− = TheXmlB !XmlB
74− | TheAnyXmlC !AnyXmlC
75− deriving (Eq, Show)
76−
77−instance NFData AnyXmlB where
78− rnf = rwhnf
79−
80−instance FromDom AnyXmlB where
81− fromDom = do
82− tp <- parseAttribute
83− (matchName "{http://www.w3.org/2001/XMLSchema-instance}type")
84− Right
85− case tp of
86− "B" -> TheXmlB <$> fromDom
87− "C" -> TheAnyXmlC <$> fromDom
88− _ -> throwParserError (PEOther "Unexpected type")
89−
90−instance ToXML AnyXmlB where
91− toXML (TheXmlB a) = toXML a
92− toXML (TheAnyXmlC a) = toXML a
93−
94−instance ToXmlParentAttributes AnyXmlB where
95− toXmlParentAttributes (TheXmlB a) =
96− ("{http://www.w3.org/2001/XMLSchema-instance}type", "B")
97− : toXmlParentAttributes a
98− toXmlParentAttributes (TheAnyXmlC a) =
99− ("{http://www.w3.org/2001/XMLSchema-instance}type", "C")
100− : toXmlParentAttributes a
101−
golden/import.xsddeleted−16
@@ -1,16 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema
3− xmlns:xs="http://www.w3.org/2001/XMLSchema"
4− xmlns:my="uri:my"
5− xmlns:my1="uri:my1"
6− targetNamespace="uri:my1"
7− >
8− <xs:import schemaLocation="imported.xsd" namespace="uri:my"/>
9− <xs:element name="person">
10− <xs:complexType>
11− <xs:sequence>
12− <xs:element name="name" type="my:stringtype"/>
13− </xs:sequence>
14− </xs:complexType>
15− </xs:element>
16−</xs:schema>
golden/import.xsd.hsdeleted−33
@@ -1,33 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: uri:my:stringtype
18−-}
19−newtype XmlStringtype
20− = XmlStringtype
21− { unXmlStringtype :: Text
22− } deriving (Show, Eq, NFData, ToXML)
23−
24−instance FromDom XmlStringtype where
25− fromDom = XmlStringtype <$> fromDom
26−
27−{-|
28−Generated from: uri:my1:person
29−-}
30−"Person" =:= record ParserAndGenerator
31− ! "{uri:my1}name" [t|XmlStringtype|]
32−
33−
golden/import_ambig.xsddeleted−26
@@ -1,26 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema
3− xmlns:xs="http://www.w3.org/2001/XMLSchema"
4− xmlns:my="uri:my"
5− xmlns:my1="uri:my1"
6− targetNamespace="uri:my1"
7− >
8− <xs:import schemaLocation="imported.xsd" namespace="uri:my"/>
9− <xs:simpleType name="stringtype">
10− <xs:restriction base="xs:string"/>
11− </xs:simpleType>
12− <xs:element name="AaBb">
13− <xs:complexType>
14− <xs:sequence>
15− <xs:element name="name" type="my:stringtype"/>
16− </xs:sequence>
17− </xs:complexType>
18− </xs:element>
19− <xs:element name="AaBc">
20− <xs:complexType>
21− <xs:sequence>
22− <xs:element name="name" type="my1:stringtype"/>
23− </xs:sequence>
24− </xs:complexType>
25− </xs:element>
26−</xs:schema>
golden/import_ambig.xsd.hsdeleted−50
@@ -1,50 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: uri:my:stringtype
18−-}
19−newtype XmlStringtype
20− = XmlStringtype
21− { unXmlStringtype :: Text
22− } deriving (Show, Eq, NFData, ToXML)
23−
24−instance FromDom XmlStringtype where
25− fromDom = XmlStringtype <$> fromDom
26−
27−{-|
28−Generated from: uri:my1:AaBb
29−-}
30−"AaBb" =:= record ParserAndGenerator
31− ! "{uri:my1}name" [t|XmlStringtype|]
32−
33−{-|
34−Generated from: uri:my1:stringtype
35−-}
36−newtype XmlStringtype1
37− = XmlStringtype1
38− { unXmlStringtype1 :: Text
39− } deriving (Show, Eq, NFData, ToXML)
40−
41−instance FromDom XmlStringtype1 where
42− fromDom = XmlStringtype1 <$> fromDom
43−
44−{-|
45−Generated from: uri:my1:AaBc
46−-}
47−"AaBc1" =:= record ParserAndGenerator
48− ! "{uri:my1}name" [t|XmlStringtype1|]
49−
50−
golden/imported.xsddeleted−9
@@ -1,9 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema
3− xmlns:xs="http://www.w3.org/2001/XMLSchema"
4− targetNamespace="uri:my"
5− >
6− <xs:simpleType name="stringtype">
7− <xs:restriction base="xs:string"/>
8− </xs:simpleType>
9−</xs:schema>
golden/imported.xsd.hsdeleted−27
@@ -1,27 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: uri:my:stringtype
18−-}
19−newtype XmlStringtype
20− = XmlStringtype
21− { unXmlStringtype :: Text
22− } deriving (Show, Eq, NFData, ToXML)
23−
24−instance FromDom XmlStringtype where
25− fromDom = XmlStringtype <$> fromDom
26−
27−
golden/include.xsddeleted−5
@@ -1,5 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:include schemaLocation="included.xsd"/>
4− <xs:element name="name" type="stringtype"/>
5−</xs:schema>
golden/include.xsd.hsdeleted−27
@@ -1,27 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: stringtype
18−-}
19−newtype XmlStringtype
20− = XmlStringtype
21− { unXmlStringtype :: Text
22− } deriving (Show, Eq, NFData, ToXML)
23−
24−instance FromDom XmlStringtype where
25− fromDom = XmlStringtype <$> fromDom
26−
27−
golden/included.xsddeleted−6
@@ -1,6 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:simpleType name="stringtype">
4− <xs:restriction base="xs:string"/>
5− </xs:simpleType>
6−</xs:schema>
golden/included.xsd.hsdeleted−27
@@ -1,27 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: stringtype
18−-}
19−newtype XmlStringtype
20− = XmlStringtype
21− { unXmlStringtype :: Text
22− } deriving (Show, Eq, NFData, ToXML)
23−
24−instance FromDom XmlStringtype where
25− fromDom = XmlStringtype <$> fromDom
26−
27−
golden/seq.xsddeleted−14
@@ -1,14 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:simpleType name="str">
4− <xs:restriction base="xs:string"/>
5− </xs:simpleType>
6− <xs:element name="customer">
7− <xs:complexType>
8− <xs:sequence>
9− <xs:element name="firstName" type="str"/>
10− <xs:element name="lastName" type="str"/>
11− </xs:sequence>
12− </xs:complexType>
13− </xs:element>
14−</xs:schema>
golden/seq.xsd.hsdeleted−34
@@ -1,34 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: str
18−-}
19−newtype XmlStr
20− = XmlStr
21− { unXmlStr :: Text
22− } deriving (Show, Eq, NFData, ToXML)
23−
24−instance FromDom XmlStr where
25− fromDom = XmlStr <$> fromDom
26−
27−{-|
28−Generated from: customer
29−-}
30−"Customer" =:= record ParserAndGenerator
31− ! "firstName" [t|XmlStr|]
32− ! "lastName" [t|XmlStr|]
33−
34−
golden/simple.xsddeleted−25
@@ -1,25 +0,0 @@
1−<?xml version="1.0"?>
2−<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3− <xs:simpleType name="stringtype">
4− <xs:annotation>
5− <xs:documentation>Blah</xs:documentation>
6− </xs:annotation>
7− <xs:restriction base="xs:string"/>
8− </xs:simpleType>
9− <xs:element name="name" type="stringtype"/>
10− <xs:element name="a">
11− <xs:annotation>
12− <xs:documentation>A blah</xs:documentation>
13− </xs:annotation>
14− <xs:complexType>
15− <xs:sequence>
16− <xs:element name="a" type="stringtype"/>
17− <xs:element name="b" minOccurs="1" type="stringtype"/>
18− <xs:element name="c" minOccurs="0" maxOccurs="1" type="stringtype"/>
19− <xs:element name="d" minOccurs="1" maxOccurs="2" type="stringtype"/>
20− <xs:element name="e" minOccurs="1" maxOccurs="unbounded" type="stringtype"/>
21− <xs:element name="f" type="xs:decimal"/>
22− </xs:sequence>
23− </xs:complexType>
24− </xs:element>
25−</xs:schema>
golden/simple.xsd.hsdeleted−40
@@ -1,40 +0,0 @@
1−-- This file was generated by xsd-isogen version 0.1.0.0
2−-- https://github.com/dredozubov/xsd-isogen
3−
4−{-# OPTIONS_GHC -Wno-unused-imports #-}
5−module Dummy where
6−
7−import Control.DeepSeq
8−import Data.Scientific
9−import Data.THGen.XML
10−import Text.XML.DOM.Parser
11−import Text.XML.Writer
12−import Text.XML.ParentAttributes
13−import Prelude hiding ((*), (+))
14−
15−
16−{-|
17−Generated from: stringtype
18−
19−Blah
20−-}
21−newtype XmlStringtype
22− = XmlStringtype
23− { unXmlStringtype :: Text
24− } deriving (Show, Eq, NFData, ToXML)
25−
26−instance FromDom XmlStringtype where
27− fromDom = XmlStringtype <$> fromDom
28−
29−{-|
30−Generated from: a
31−-}
32−"A" =:= record ParserAndGenerator
33− ! "a" [t|XmlStringtype|]
34− ! "b" [t|XmlStringtype|]
35− ? "c" [t|XmlStringtype|]
36− + "d" [t|XmlStringtype|]
37− + "e" [t|XmlStringtype|]
38− ! "f" [t|Scientific|]
39−
40−
golden/test.shdeleted−5
@@ -1,5 +0,0 @@
1−#!/bin/bash
2−
3−for file in *.xsd; do
4− cabal run -v0 xsd-isogen -- -i $file > $file.hs
5−done
src/BuiltInTypes.hsdeleted−67
@@ -1,67 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−module BuiltInTypes
4−( builtInTypes
5−)
6−where
7−
8−import Data.Map (Map)
9−import qualified Data.Map as Map
10−
11−import qualified Xsd
12−
13−import Gen
14−
15−builtInTypes :: Map Xsd.QName TypeName
16−builtInTypes = Map.fromList . map qualify $
17− [ ("anyURI", "Text")
18− , ("base64Binary", "ByteString")
19− , ("boolean", "Bool")
20− , ("date", "Date")
21− , ("dateTime", "Text")
22− , ("dateTimeStamp", "Text")
23− , ("decimal", "Scientific")
24− , ("integer", "Integer")
25− , ("long", "Integer")
26− , ("int", "Integer")
27− , ("short", "Integer")
28− , ("byte", "Integer")
29− , ("nonNegativeInteger", "Integer")
30− , ("positiveInteger", "Integer")
31− , ("unsignedLong", "Integer")
32− , ("unsignedInt", "Integer")
33− , ("unsignedByte", "Integer")
34− , ("nonPositiveInteger", "Integer")
35− , ("negativeInteger", "Integer")
36− , ("float", "Float")
37− , ("double", "Scientific")
38− , ("gDay", "Day")
39− , ("gMonth", "Text")
40− , ("gMonthDay", "Text")
41− , ("gYear", "Text")
42− , ("gYearMonth", "Text")
43− , ("hexBinary", "Text")
44− , ("NOTATION", "Text")
45− , ("QName", "Text")
46− , ("string", "Text")
47− , ("normalizedString", "Text")
48− , ("token", "Text")
49− , ("language", "Text")
50− , ("NCName", "Text")
51− , ("Entity", "Text")
52− , ("ID", "Text")
53− , ("IDREF", "Text")
54− , ("NMToken", "Text")
55− , ("time", "Text")
56− , ("duration", "Text")
57− ]
58− where
59− qualify (n, t) =
60− let
61− tn = TypeName
62− { tnName = t
63− , tnPrefixed = t
64− , tnQName = qname
65− }
66− qname = Xsd.QName (Just (Xsd.Namespace Xsd.schemaNamespace)) n
67− in (qname, tn)
src/Gen.hsdeleted−213
@@ -1,213 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3−
4−module Gen
5−( GenState(..)
6−, Gen
7−, runGen
8−, TypeName(..)
9−, getMode
10−, writeCode
11−, warn
12−, genError
13−, resolveType
14−, resolveTypeName
15−, knownTypeName
16−, extensions
17−, makeTypeName
18−, makeFieldName
19−, makeEnumName
20−)
21−where
22−
23−import qualified Data.Char as Char
24−import Data.Text (Text)
25−import qualified Data.Text as Text
26−import Data.Maybe
27−import Data.Set (Set)
28−import qualified Data.Set as Set
29−import Data.Map (Map)
30−import qualified Data.Map as Map
31−import Control.Monad
32−import Control.Monad.Trans
33−import Control.Monad.Trans.State
34−import Control.Monad.Trans.Except
35−import qualified Xsd
36−
37−import Options (GenType(..))
38−
39−-- | Generator state
40−data GenState = GenState
41− { gsTypes :: Map Xsd.QName Xsd.Type
42− -- ^ All global types
43− , gsExtensions :: Map Xsd.QName [(Xsd.QName, Xsd.Type)]
44− -- ^ Lift of extension of the specified type
45− , gsKnownTypes :: Map Xsd.QName TypeName
46− -- ^ Global types that were already processed and their generated names
47− , gsBoundTypeName :: Set Text
48− -- ^ prefixed names that were already used
49− , gsBoundFields :: Set Text
50− -- ^ field names that were already used
51− , gsMode :: GenType
52− , gsCode :: [Text]
53− , gsWarnings :: [Text]
54− }
55−
56−-- | Generator monad
57−newtype Gen a = Gen
58− { fromGen :: StateT GenState (Except String) a
59− }
60− deriving (Functor, Applicative, Monad)
61−
62−-- | Run generator
63−runGen :: GenState -> Gen a -> Either String GenState
64−runGen s m = runExcept $ execStateT (fromGen m) s
65−
66−getMode :: Gen GenType
67−getMode = Gen $ gets gsMode
68−
69−-- | Add lines to the output
70−writeCode :: [Text] -> Gen ()
71−writeCode code = Gen $ modify' $ \s -> s
72− { gsCode = reverse code ++ gsCode s
73− }
74−
75−-- | Emit warning
76−warn :: Text -> Gen ()
77−warn msg = Gen $ modify' $ \s -> s
78− { gsWarnings = ("WARNING: " <> msg) : gsWarnings s
79− }
80−
81−-- | Usually we prefix types with "Xml", but for records we need plain name
82−--
83−-- Note that built-in types doesn't have prefix, so prefixed name is
84−-- the same as the plain one.
85−data TypeName = TypeName
86− { tnName :: Text
87− -- ^ plain name
88− , tnPrefixed :: Text
89− -- ^ name with "Xml" prefix
90− , tnQName :: Xsd.QName
91− -- ^ the original name
92− }
93−
94−-- | Allocate new type name for given qualified name
95−--
96−-- It checks for ambiguous type names and fields
97−makeTypeName :: Xsd.QName -> Xsd.Type -> Gen TypeName
98−makeTypeName name tp = go Nothing
99− where
100− go suffix = do
101− let
102− typeName = capitalize (Xsd.qnName name)
103− <> maybe "" (Text.pack . show) suffix
104− prefixed = "Xml" <> typeName
105− next = case suffix of
106− Nothing -> Just (1 :: Int)
107− Just i -> Just (succ i)
108− bound <- Gen $ gets (Set.member prefixed . gsBoundTypeName)
109− duplicateFields <- hasDuplicateFields typeName tp
110− if bound || duplicateFields
111− then go next
112− else do
113− let
114− tn = TypeName
115− { tnName = typeName
116− , tnPrefixed = prefixed
117− , tnQName = name
118− }
119− Gen $ modify' $ \s -> s
120− { gsKnownTypes = Map.insert name tn (gsKnownTypes s)
121− , gsBoundTypeName = Set.insert prefixed (gsBoundTypeName s)
122− }
123− return tn
124−
125−makeFieldName :: TypeName -> Xsd.QName -> Gen Text
126−makeFieldName typeName name = do
127− -- here we remember that the field name is bound, so that
128− -- hasDuplicateFields can check for ambiguous fields
129− let prefixed = makePrefixedField (tnName typeName) name
130− Gen $ modify' $ \s -> s
131− { gsBoundFields = Set.insert prefixed (gsBoundFields s)
132− }
133− return (qualifier <> Xsd.qnName name)
134− where
135− qualifier = maybe ""
136− (\(Xsd.Namespace ns) -> "{" <> ns <> "}")
137− (Xsd.qnNamespace name)
138−
139−-- | Make value for enum
140−--
141−-- We may need to handle duplicate enum values here
142−makeEnumName :: Text -> Gen Text
143−makeEnumName = return . capitalize
144−
145−-- | Check whether field name is ambiguous
146−hasDuplicateFields :: Text -> Xsd.Type -> Gen Bool
147−hasDuplicateFields typeName tp = do
148− bound <- forM (allFields tp) $ \f -> do
149− let prefixed = makePrefixedField typeName f
150− Gen $ gets (Set.member prefixed . gsBoundFields)
151− return (or bound)
152−
153−-- | Get all fields from the type
154−allFields :: Xsd.Type -> [Xsd.QName]
155−allFields (Xsd.TypeSimple _) = []
156−allFields (Xsd.TypeComplex t) =
157− case Xsd.complexContent t of
158− Xsd.ContentPlain c ->
159− case Xsd.plainContentModel c of
160− Just (Xsd.Sequence es) -> mapMaybe elementName es
161− _ -> []
162− Xsd.ContentSimple _ -> []
163− Xsd.ContentComplex (Xsd.ComplexContentExtension e) ->
164− case Xsd.complexExtensionModel e of
165− Just (Xsd.Sequence es) -> mapMaybe elementName es
166− _ -> []
167− Xsd.ContentComplex (Xsd.ComplexContentRestriction _) -> []
168− where
169− elementName = Xsd.refOr
170− (const Nothing)
171− (Just . Xsd.elementName)
172−
173−-- | Prefix field name with based on the type name
174−makePrefixedField :: Text -> Xsd.QName -> Text
175−makePrefixedField typeName field = prefix <> Xsd.qnName field
176− where
177− prefix
178− = Text.map Char.toLower
179− . Text.filter (\c -> Char.isUpper c || Char.isDigit c)
180− $ typeName
181−
182−-- | Get generated name for the type name
183−--
184−-- Returns Nothing if the type was not generated yet
185−knownTypeName :: Xsd.QName -> Gen (Maybe TypeName)
186−knownTypeName name = Gen $ gets (Map.lookup name . gsKnownTypes)
187−
188−extensions :: Xsd.QName -> Gen [(Xsd.QName, Xsd.Type)]
189−extensions base = Gen $ gets (Map.findWithDefault [] base . gsExtensions)
190−
191−-- | Returns type for the reference
192−resolveType :: Xsd.QName -> Gen Xsd.Type
193−resolveType name = do
194− mt <- Gen $ gets (Map.lookup name . gsTypes)
195− case mt of
196− Just t -> return t
197− Nothing -> genError ("unknown reference to " <> show name)
198−
199−-- | Returns type type for the reference
200−--
201−-- It should already be generated
202−resolveTypeName :: Xsd.QName -> Gen TypeName
203−resolveTypeName name = knownTypeName name
204− >>= maybe (genError ("unresolved type: " <> show name)) return
205−
206−-- | Fail the generator
207−genError :: String -> Gen a
208−genError = Gen . lift . throwE
209−
210−capitalize :: Text -> Text
211−capitalize t
212− | Text.null t = t
213− | otherwise = Text.singleton (Char.toUpper (Text.head t)) <> Text.tail t
src/Main.hs+395−438
@@ -1,450 +1,407 @@
1+{-# LANGUAGE FlexibleInstances #-}
2+{-# LANGUAGE LambdaCase #-}
13{-# LANGUAGE OverloadedStrings #-}
24
35module Main
4−( main
5−)
6−where
7−
8−import Data.Text (Text)
9−import qualified Data.Text as Text
10−import qualified Data.Text.IO as Text
11−import Data.Maybe
12−import qualified Data.List as List
13−import qualified Data.Set as Set
14−import Data.Map (Map)
15−import qualified Data.Map as Map
16−import Control.Monad
17−import qualified System.IO as IO
18−import qualified Xsd
19−
20−import Options
21−import Gen
22−import References
23−import BuiltInTypes
6+ ( main
7+ ) where
8+
9+import Control.Monad.RWS.CPS (RWS, execRWS)
10+import Control.Monad.Reader
11+import Control.Monad.State.Strict
12+import Control.Monad.Writer.CPS (Writer, tell, execWriter)
13+import Data.ByteString.Lazy as BL
14+import Data.Char as C
15+import Data.Default
16+import Data.Foldable as F
17+import Data.List as L
18+import Data.Map.Strict as M
19+import Data.Set as S
20+import Data.Text as T
21+import Data.Text.IO as T
22+import Data.Traversable
23+import Debug.Trace
24+import System.Environment
25+import System.IO
26+import Text.XSD
27+
28+
29+data GenType = Parser | Generator | Both
30+ deriving (Read, Show)
31+
32+genTypeToText :: GenType -> Text
33+genTypeToText Parser = "Parser"
34+genTypeToText Generator = "Generator"
35+genTypeToText Both = "Both"
36+
37+type GenMonad = ReaderT DatatypeMap (Writer Text)
38+
39+class References a where
40+ references :: a -> [Text]
41+
42+instance References Datatype where
43+ references (TypeComplex (ComplexType _ _ _ mmgs)) =
44+ case mmgs of
45+ Just mgs -> case mgs of
46+ CTSequence els -> F.concatMap references els
47+ CTChoice els -> F.concatMap references els
48+ CTAll els -> F.concatMap references els
49+ Nothing -> []
50+ references (TypeSimple _) = []
51+
52+instance References Element where
53+ references (Element _ t _ _ _) = references t
54+
55+instance References DatatypeRef where
56+ references (DatatypeRef ty) = [ty]
57+ references (InlineComplex dt) = references dt
58+
59+instance References a => References [a] where
60+ references = F.concatMap references
61+
62+-- | 'DatatypeMap' are the types left to process
63+-- 'S.Set Text' are the types already processed.
64+type PreMonad = StateT (DatatypeMap, S.Set Text) (Writer [(Text, Datatype)])
65+
66+type PreElemMonad = RWS DatatypeMap [Element] [Element]
67+
68+-- | Marks the given type as processed.
69+proceed :: Text -> Datatype -> PreMonad ()
70+proceed t dt = do
71+ tell [(t, dt)]
72+ modify $ \(f,s) -> (M.delete t f, S.insert t s)
73+
74+-- | Marks element as processed.
75+proceed' :: Element -> PreElemMonad ()
76+proceed' el = do
77+ tell [el]
78+ modify $ L.delete el
79+
80+untwistDeps :: [Element] -> DatatypeMap -> ([(Text, Datatype)], [Element])
81+untwistDeps e dm = (dList, e')
82+ where
83+ dList = nub $ execWriter $ do
84+ (a, _) <- runStateT sortDatatypesByDeps (dm, S.empty)
85+ return a
86+ (_, e') = execRWS sortElemsByDeps (M.fromList dList) e
87+
88+sortElemsByDeps :: PreElemMonad ()
89+sortElemsByDeps = do
90+ els <- get
91+ if Prelude.null els then pure () else do
92+ let first = Prelude.head els
93+ -- traceM $ "sortElemsByDeps: " <> show first
94+ case references first of
95+ [] -> proceed' first >> sortElemsByDeps
96+ xs -> do
97+ results <- traverse memberDatatype xs
98+ if L.and results
99+ then proceed' first >> sortElemsByDeps
100+ else do
101+ let failed = fmap snd $ L.filter (not . fst) $ L.zip results xs
102+ error $ "impossible to lookup types: " <> show failed
103+
104+memberDatatype :: Text -> PreElemMonad Bool
105+memberDatatype ty = do
106+ -- traceM $ "memberDatatype: " <> show ty
107+ dm <- ask
108+ case M.lookup ty dm of
109+ Just _ -> return True
110+ Nothing -> return False
111+
112+sortDatatypesByDeps :: PreMonad ()
113+sortDatatypesByDeps = do
114+ (dm, _) <- get
115+ if M.null dm then pure () else do
116+ let first = Prelude.head (M.toList dm)
117+ traceM $ "sortDatatypesByDeps: " <> show first
118+ case references $ snd first of
119+ [] -> uncurry proceed first >> sortDatatypesByDeps
120+ xs -> do
121+ traverse_ lookupDatatype xs
122+ uncurry proceed first
123+ sortDatatypesByDeps
124+
125+lookupDatatype :: Text -> PreMonad ()
126+lookupDatatype ty = do
127+ traceM $ "lookupDatatype: " <> show ty
128+ (dm, s) <- get
129+ case M.lookup ty dm of
130+ Nothing -> if S.member ty s then pure () else
131+ error $ "can't look up datatype: " <> show ty
132+ Just typ -> case references typ of
133+ [] -> proceed ty typ
134+ xs -> traverse_ lookupDatatype xs >> proceed ty typ
135+
136+class Capitalizable t where
137+ capitalize :: t -> t
138+
139+instance Capitalizable String where
140+ capitalize [] = []
141+ capitalize (a:as) = C.toUpper a : as
142+
143+instance Capitalizable Text where
144+ capitalize t
145+ | T.null t = t
146+ | otherwise = T.singleton (C.toUpper (T.head t)) <> T.tail t
147+
148+data DataFlavour = QQ | Plain
149+
150+-- TODO: improve after moving some XML types to xml-isogen
151+simpleTypeToIsoType :: DataFlavour -> SimpleAtomicType -> Text
152+simpleTypeToIsoType fl = \case
153+ STAnyURI -> wrap fl "Text"
154+ STBase64Binary -> wrap fl "ByteString"
155+ STBoolean -> wrap fl "Bool"
156+ STDate -> wrap fl "Date \"%YYYYj\""
157+ STDateTime -> wrap fl "Text"
158+ STDateTimeStamp -> wrap fl "Text"
159+ STDecimal DTDecimal -> wrap fl "Double"
160+ (STDecimal _) -> wrap fl "Integer"
161+ STDouble -> wrap fl "Double"
162+ (STDuration _) -> wrap fl "Integer"
163+ STFloat -> wrap fl "Float"
164+ STGDay -> wrap fl "Day"
165+ STGMonth -> wrap fl "Text"
166+ STGMonthDay -> wrap fl "Text"
167+ STGYear -> wrap fl "Text"
168+ STGYearMonth -> wrap fl "Text"
169+ STHexBinary -> wrap fl "Text"
170+ STNOTATION -> wrap fl "Text"
171+ STQName -> wrap fl "Text"
172+ (STString _) -> wrap fl "Text"
173+ STTime -> wrap fl "Text"
174+ where
175+ wrap QQ t = "[t|" <> t <> "|]"
176+ wrap Plain t = t
24177
25−main :: IO ()
26−main = do
27− opts <- getOptions
28− schema <- Xsd.getSchema (oInput opts)
29− res <- either fail return
30− (generate opts schema)
31− mapM_ (Text.hPutStrLn IO.stderr) (resultWarnings res)
32− Text.putStrLn (resultCode res)
33−
34−data Result = Result
35− { resultCode :: Text
36− , resultWarnings :: [Text]
37− }
38−
39−generate :: Options -> Xsd.Schema -> Either String Result
40−generate opts schema = do
178+tellGen
179+ :: [Text] -- generated code
180+ -> Text -- comment
181+ -> GenMonad ()
182+tellGen code comment =
183+ tell $ "\n" <> comment <> T.unlines code
184+
185+runGen :: DatatypeMap -> GenMonad a -> Text
186+runGen dm act = execWriter $ runReaderT act dm
187+
188+generateIsoXml :: GenType -> XSD -> Text
189+generateIsoXml genType (XSD (e,dm)) =
41190 let
42− types = Map.union (Xsd.schemaTypes schema)
43− (elementsToTypes (Xsd.schemaElements schema))
44− s <- runGen (initialGenState opts types) $ do
45− genHeader opts
46− genTypes types
47− Right Result
48− { resultCode = Text.unlines (reverse (gsCode s))
49− , resultWarnings = reverse (gsWarnings s)
50− }
51−
52−elementsToTypes :: Map Xsd.QName Xsd.Element -> Map Xsd.QName Xsd.Type
53−elementsToTypes = List.foldl' step Map.empty . Map.toList
191+ (dList, el) = untwistDeps e dm
192+ in (header genType <>) . runGen dm $ do
193+ for_ dList $ \(t,dt) ->
194+ generateIsoDatatype genType t dt []
195+ for_ el (generateIsoRecord genType)
196+
197+toQualifier :: Int -> Int -> Text
198+toQualifier minOc maxOc
199+ | minOc == 1 && maxOc == 1 = "!"
200+ | minOc == 0 && maxOc == 1 = "?"
201+ | minOc == 1 && maxOc > minOc = "+"
202+ | minOc == 1 && maxOc < minOc = error "maxOccurs < minOccurs"
203+ | otherwise = "*"
204+
205+header :: GenType -> Text
206+header genType = T.unlines $
207+ [ "module Dummy where"
208+ , ""
209+ , "import Control.DeepSeq"
210+ , "import Data.THGen.XML"
211+ ] <> specImports <>
212+ [ "import Prelude hiding ((*), (+))"
213+ , "" ]
214+ where
215+ specImports = case genType of
216+ Generator -> [ xmlWriter ]
217+ Parser -> [ domParser ]
218+ Both -> [ domParser, xmlWriter ]
219+ xmlWriter, domParser :: Text
220+ xmlWriter = "import Text.XML.Writer"
221+ domParser = "import Text.XML.DOM.Parser.FromDom"
222+
223+quote :: Text -> Text
224+quote t = "\"" <> t <> "\""
225+
226+-- | Nothing means unknown name
227+typeName :: DatatypeRef -> Maybe Text
228+typeName (InlineComplex dt) = result
229+ where
230+ result = case dt of
231+ TypeComplex (ComplexType n _ _ _) -> n
232+ TypeSimple (STAtomic _ sat _ _) -> Just $ simpleTypeToIsoType QQ sat
233+typeName (DatatypeRef t) = Just t
234+
235+generateIsoRecord :: GenType -> Element -> GenMonad ()
236+generateIsoRecord
237+ genType
238+ (Element (_, laxName) elXtype _ _ elAnnotations) = do
239+ written <- ask
240+ case elXtype of
241+ InlineComplex dt ->
242+ generateIsoDatatype genType laxName dt elAnnotations
243+ DatatypeRef nam -> if M.member nam written
244+ then pure ()
245+ else error $ "Implementation failure: "
246+ <> show nam <> " type never encountered before"
247+
248+data CommentType = Haddock | Regular
249+
250+toComment :: CommentType -> [Annotation] -> Text
251+toComment ct ann = case texts of
252+ [] -> ""
253+ (h:tl) -> T.unlines ((prefix <> h) : fmap ("-- "<>) tl)
254+ where
255+ texts = stripTexts $ F.concatMap (wrap80 . fromDocumentation) ann
256+ stripTexts = \case
257+ [] -> []
258+ l@(h:tl) -> if T.all (\x -> x == ' ' || x == '\n') h then stripTexts tl else l
259+ prefix = case ct of
260+ Haddock -> "-- | "
261+ Regular -> "-- "
262+
263+fromDocumentation :: Annotation -> Text
264+fromDocumentation (Documentation t) = t
265+
266+wrap80 :: Text -> [Text]
267+wrap80 = L.foldl' go [] . T.split (==' ')
54268 where
55− step types (_, e) = case Xsd.elementType e of
56− Xsd.Ref _ -> types
57− Xsd.Inline t -> Map.insert (Xsd.elementName e) t types
58−
59−genTypes :: Map Xsd.QName Xsd.Type -> Gen ()
60−genTypes types = mapM_ (uncurry genTopType) . Map.toList $ types
61−
62−genTopType :: Xsd.QName -> Xsd.Type -> Gen ()
63−genTopType = genType []
64−
65−genType :: [Xsd.Annotation] -> Xsd.QName -> Xsd.Type -> Gen ()
66−genType annotations name tp = do
67− known <- knownTypeName name
68− case known of
69− Just _ -> return () -- already generated
70− Nothing -> do
71− -- we should generate dependencies before the type itself to make
72− -- sure they are in scope when xml-isogen quotes them
73− -- (stage restriction in TH)
74− genDependencies tp
75− typeName <- makeTypeName name tp
76− case tp of
77− Xsd.TypeSimple t -> genSimpleType typeName t annotations
78− Xsd.TypeComplex t -> genComplexType typeName t annotations
79− genExtension name
80−
81−genExtension :: Xsd.QName -> Gen ()
82−genExtension base = do
83− exts <- extensions base
84− case exts of
85− [] -> return ()
86− types -> do
87− mapM_ (uncurry genTopType) types
88− baseTypeName <- tnPrefixed <$> resolveTypeName base
89− writeCode
90− [ "data Any" <> baseTypeName
91− , " = The" <> baseTypeName <> " !" <> baseTypeName
92− ]
93− let
94− mkConstructor (n, _) = do
95− tn <- tnPrefixed <$> resolveTypeName n
96− exts' <- extensions n
269+ go [] e = [e]
270+ go l e =
271+ let last' = L.last l
272+ in if T.length last' + T.length e >= 73 -- 80 minus "-- | " and ' '
273+ then l <> pure e
274+ else L.init l <> [L.last l <> " " <> e]
275+
276+generateIsoDatatype
277+ :: GenType
278+ -> (Maybe Text) -- ^ Explicitly provided name, used for inline complexType's
279+ -> Datatype
280+ -> [Annotation]
281+ -> GenMonad ()
282+ -- ^ (type name for lookups, generated code)
283+generateIsoDatatype
284+ genType
285+ eName
286+ (TypeComplex (ComplexType iName attrs annotations mGroupSchema))
287+ annotationsRec = do
288+ name <- case eName of
289+ Just name -> pure name
290+ Nothing -> case iName of
291+ Just name' -> pure name'
292+ Nothing -> error $ "[generateIsoDatatype] no name was provided"
293+ case mGroupSchema of
294+ Just groupSchema -> case groupSchema of
295+ CTSequence elems -> do
296+ fields <- for elems (generateIsoField genType)
97297 let
98− n' = case exts' of
99− [] -> tn
100− _ -> "Any" <> tn
101− return (" | The" <> n' <> " !" <> n')
102− constructors <- mapM mkConstructor types
103− writeCode constructors
104− writeCode
105− [ " deriving (Eq, Show)"
106− , ""
107− ]
108− writeCode
109− [ "instance NFData Any" <> baseTypeName <> " where"
110− , " rnf = rwhnf"
111− , " "
112− ]
113− mode <- getMode
114− unless (mode == Generator) $ do
115− writeCode
116− [ "instance FromDom Any" <> baseTypeName <> " where"
117− , " fromDom = do"
118− , " tp <- parseAttribute"
119− , " (matchName " <>
120− "\"{http://www.w3.org/2001/XMLSchema-instance}type\")"
121− , " Right"
122− , " case tp of"
123− ]
124− let
125− mkClause n = do
126− tn <- resolveTypeName n
127− exts' <- extensions n
128− n' <- case exts' of
129− [] -> return (tnPrefixed tn)
130− _ | n == base -> return (tnPrefixed tn)
131− _ -> return ("Any" <> tnPrefixed tn)
132− return $ mconcat
133− [ " \""
134− , tnName tn
135− , "\" -> The"
136− , n'
137− , " <$> fromDom"
138− ]
139− clauses <- mapM mkClause (base : map fst types)
140− writeCode clauses
141− writeCode
142− [ " _ -> throwParserError (PEOther \"Unexpected type\")"
143− , ""
144− ]
145− unless (mode == Parser) $ do
146− writeCode
147− [ "instance ToXML Any" <> baseTypeName <> " where"
148− , " toXML (The" <> baseTypeName <> " a) = toXML a"
149− ]
150− let
151− mkClause (n, _) = do
152− tn <- tnPrefixed <$> resolveTypeName n
153− exts' <- extensions n
154− let
155− n' = case exts' of
156− [] -> tn
157− _ -> "Any" <> tn
158− return (" toXML (The" <> n' <> " a) = toXML a")
159− clauses <- mapM mkClause types
160− writeCode clauses
161− writeCode [""]
162− writeCode
163− [ "instance ToXmlParentAttributes Any" <> baseTypeName <> " where"
164− ]
165− let
166− toAttrLine n = do
167− tn <- resolveTypeName n
168− exts' <- extensions n
169− n' <- case exts' of
170− [] -> return (tnPrefixed tn)
171− _ | n == base -> return (tnPrefixed tn)
172− _ -> return ("Any" <> tnPrefixed tn)
173− return
174− [ " toXmlParentAttributes (The" <> n' <> " a) ="
175− , " (\"{http://www.w3.org/2001/XMLSchema-instance}type\", \""
176− <> tnName tn <> "\")"
177− , " : toXmlParentAttributes a"
178− ]
179− attrLines <- mapM toAttrLine (base : map fst types)
180− writeCode (concat attrLines)
181−
182−genDependencies :: References a => a -> Gen ()
183−genDependencies a = forM_ (references a) $ \name -> do
184− known <- knownTypeName name
185− case known of
186− Just _ -> return () -- already generated
187− Nothing -> do
188− tp <- resolveType name
189− genTopType name tp
190−
191−genSimpleType :: TypeName -> Xsd.SimpleType -> [Xsd.Annotation]-> Gen ()
192−genSimpleType tn (Xsd.AtomicType restriction ann) parentAnn = do
298+ comment = toComment Haddock $ annotationsRec
299+ <> [Documentation ""]
300+ <> annotations
301+ header =
302+ (quote $ capitalize name)
303+ <> " =:= record "
304+ <> genTypeToText genType
305+ tellGen (header : fields) comment
306+generateIsoDatatype
307+ genType
308+ eName
309+ (TypeSimple (STAtomic iName sat annotations restrictions))
310+ annotationsRec = do
311+ name <- case eName of
312+ Just name -> pure name
313+ Nothing -> pure iName
314+ let
315+ comment =
316+ toComment Haddock $ annotationsRec
317+ <> [Documentation ""]
318+ <> annotations
319+ isEnumeration (Enumeration _) = True
320+ fromEnumeration (Enumeration x) = x
321+ enums = Prelude.filter isEnumeration restrictions
322+ typeStr = simpleTypeToIsoType QQ sat
323+ if Prelude.length enums > 0
324+ then tellGen
325+ (generateEnum
326+ (quote $ capitalize name)
327+ (F.concatMap fromEnumeration enums))
328+ comment
329+ else
330+ tellGen (generateNewtype genType iName sat) comment
331+
332+generateNewtype :: GenType -> Text -> SimpleAtomicType -> [Text]
333+generateNewtype genType n sat =
193334 let
194− baseName r = case Xsd.simpleRestrictionBase r of
195− Xsd.Ref n -> Just n
196− Xsd.Inline (Xsd.AtomicType r' _) -> baseName r'
197− Xsd.Inline (Xsd.ListType _ _) -> Nothing
198− Xsd.Inline (Xsd.UnionType _ _) -> Nothing
199− case baseName restriction of
200− Just _
201− | isEnum restriction
202− -> genEnum tn
203− (Xsd.simpleRestrictionConstraints restriction)
204− (parentAnn <> ann)
205− Just base ->
206− genNewtype tn base (parentAnn <> ann)
207− _ -> genUnsupported tn
208−genSimpleType typeName (Xsd.ListType _ _) _ = genUnsupported typeName
209−genSimpleType typeName (Xsd.UnionType _ _) _ = genUnsupported typeName
210−
211−genNewtype :: TypeName -> Xsd.QName -> [Xsd.Annotation] -> Gen ()
212−genNewtype tn base annots = do
213− fieldTypeName <- tnPrefixed <$> resolveTypeName base
214− mode <- getMode
335+ cons = "Xml" <> capitalize n
336+ decons = "un" <> cons
337+ parser =
338+ [ ""
339+ , "instance FromDom " <> cons <> " where"
340+ , " fromDom = " <> cons <> " <$> fromDom"
341+ ]
342+ in
343+ [ "newtype " <> cons
344+ , " = " <> cons
345+ , " { " <> decons <> " :: " <> simpleTypeToIsoType Plain sat
346+ , " } deriving (Show, Eq, NFData" <> case genType of
347+ Parser -> ")"
348+ _ -> ", ToXML)"
349+ ] <> case genType of
350+ Generator -> []
351+ _ -> parser
352+
353+generateEnum
354+ :: Text -- type name
355+ -> [Text] -- enums
356+ -> [Text] -- generated code
357+generateEnum enumName enums =
215358 let
216− typeName = tnPrefixed tn
217− fieldName = "un" <> typeName
218− toxml = case mode of
219− Parser -> ""
220− _ -> ", ToXML"
221− writeCode $ makeComments tn annots
222− writeCode
223− [ "newtype " <> typeName
224− , " = " <> typeName
225− , " { " <> fieldName <> " :: " <> fieldTypeName
226− , " } deriving (Show, Eq, NFData" <> toxml <> ")"
227− , ""
228− ]
229− unless (mode == Generator) $ writeCode
230− [ "instance FromDom " <> typeName <> " where"
231− , " fromDom = " <> typeName <> " <$> fromDom"
232− , ""
233− ]
234−
235−genEnum :: TypeName -> [Xsd.Constraint] -> [Xsd.Annotation] -> Gen ()
236−genEnum tn constraints annots = do
237− mode <- getMode
359+ enumHeader = enumName <> " Exhaustive =:= enum Both"
360+ eFields = ("& "<>) <$> enums
361+ in pure enumHeader <> eFields
362+
363+-- | Returns Just baseTypeName if type is simple, Nothing - otherwise
364+lookupSimpleBaseType
365+ :: DatatypeRef
366+ -> GenMonad (Maybe SimpleAtomicType)
367+lookupSimpleBaseType (InlineComplex _) = pure Nothing
368+lookupSimpleBaseType (DatatypeRef tyName) = do
369+ M.lookup tyName <$> ask >>= \case
370+ Just (TypeComplex _) -> pure Nothing
371+ Just (TypeSimple (STAtomic _ sat _ _)) -> pure $ Just sat
372+ Nothing -> error $ "can't look up type: " <> show tyName
373+
374+lookupSimpleType
375+ :: DatatypeRef
376+ -> GenMonad (Maybe Text)
377+lookupSimpleType (InlineComplex _) = pure Nothing
378+lookupSimpleType (DatatypeRef tyName) =
379+ asks (M.lookup tyName) >>= \case
380+ Just (TypeComplex _) -> pure Nothing
381+ Just (TypeSimple (STAtomic nam _ _ _)) -> pure $ Just nam
382+ Nothing -> error $ "can't look up type: " <> show tyName
383+
384+generateIsoField :: GenType -> Element -> GenMonad Text
385+generateIsoField genType (Element (_, name) xtype minOc maxOc annotations) = do
238386 let
239− values = map toValue constraints
240− toValue (Xsd.Enumeration v) = v
241− enumLines <- forM values $ \v -> do
242− enumName <- makeEnumName v
243− return (" & \"" <> enumName <> "\"")
244− writeCode $ makeComments tn annots
245− writeCode $ "\"" <> tnName tn <> "\" Exhaustive =:= enum "
246− <> genTypeToText mode : enumLines
247− writeCode [""]
248−
249−isEnum :: Xsd.SimpleRestriction -> Bool
250−isEnum = any isEnumConstraint . Xsd.simpleRestrictionConstraints
251− where
252− isEnumConstraint (Xsd.Enumeration _) = True
253−
254−genComplexType :: TypeName -> Xsd.ComplexType -> [Xsd.Annotation] -> Gen ()
255−genComplexType typeName t parentAnn = do
256− mode <- getMode
257− let
258− header = "\"" <> tnName typeName <> "\" =:= record "
259− <> genTypeToText mode
260− fields <- genFields typeName (Xsd.complexContent t)
261− writeCode $ makeComments typeName
262− (parentAnn <> Xsd.complexAnnotations t)
263− writeCode [header]
264− writeCode fields
265− writeCode [""]
266−
267−makeComments :: TypeName -> [Xsd.Annotation] -> [Text]
268−makeComments typeName annotations = if null annotations
269− then
270− [ "{-|"
271− , generated
272− , "-}"
273− ]
274− else
275− [ "{-|"
276− , generated
277− , ""
278− ] <> map makeDoc annotations <>
279− [ "-}"
280− ]
281− where
282− generated = "Generated from: " <> prefix <> name
283− qname = tnQName typeName
284− name = Xsd.qnName qname
285− prefix = maybe "" ((<> ":") . Xsd.fromNamespace) (Xsd.qnNamespace qname)
286− makeDoc (Xsd.Documentation docs) = docs
287−
288−-- | Generate code for record fields
289−--
290−-- The first argument - record name
291−genFields :: TypeName -> Xsd.Content -> Gen [Text]
292−genFields typeName (Xsd.ContentPlain c) =
293− maybe (return []) (genFieldsForModel typeName) (Xsd.plainContentModel c)
294−genFields _ (Xsd.ContentSimple _) = return []
295−genFields typeName (Xsd.ContentComplex (Xsd.ComplexContentExtension e)) = do
296− base <- resolveType (Xsd.complexExtensionBase e)
297− genDependencies base
298− baseFields <- case base of
299− Xsd.TypeComplex t -> genFields typeName (Xsd.complexContent t)
300− _ -> return []
301− fields <- maybe (return []) (genFieldsForModel typeName)
302− (Xsd.complexExtensionModel e)
303− return (baseFields ++ fields)
304−genFields _ (Xsd.ContentComplex (Xsd.ComplexContentRestriction _)) =
305− return []
306−
307−genFieldsForModel :: TypeName -> Xsd.ModelGroup -> Gen [Text]
308−genFieldsForModel typeName (Xsd.Sequence elements) =
309− catMaybes <$> mapM (genField typeName) elements
310−genFieldsForModel _ (Xsd.Choice _) = do
311− warn "choice: not implemented"
312− return []
313−genFieldsForModel _ (Xsd.All _) = do
314− warn "all: not implemented"
315− return []
316−
317−genField :: TypeName -> Xsd.RefOr Xsd.Element -> Gen (Maybe Text)
318−genField _ (Xsd.Ref _) = return Nothing
319−genField typeName (Xsd.Inline e) = do
320− fieldName <- makeFieldName typeName (Xsd.elementName e)
321−
322− fieldTypeName <- case Xsd.elementType e of
323− Xsd.Ref name -> do
324− tn <- tnPrefixed <$> resolveTypeName name
325− exts <- extensions name
326− case exts of
327− [] -> return tn
328− _ -> return ("Any" <> tn)
329− Xsd.Inline t -> do
330− genType (Xsd.elementAnnotations e) (Xsd.elementName e) t
331− tnPrefixed <$> resolveTypeName (Xsd.elementName e)
332−
333− qualifier <- makeQualifier (Xsd.elementOccurs e)
387+ qualifier = toQualifier minOc maxOc
388+ line <- lookupSimpleType xtype >>= \case
389+ Just tyName -> do
390+ pure $ quote name <> " [t|Xml" <> tyName <> "|]"
391+ Nothing -> case xtype of
392+ InlineComplex dt -> do
393+ generateIsoDatatype genType (Just $ capitalize name) dt annotations
394+ pure $ quote name
395+ DatatypeRef ref ->
396+ pure $ quote name <> " [t|Xml" <> capitalize ref <> "|]"
397+ pure $ " " <> qualifier <> " " <> line
334398
399+main :: IO ()
400+main = do
401+ (inFile:mode:_) <- getArgs
402+ xml <- BL.readFile inFile
335403 let
336− fieldType = if Xsd.elementNillable e
337− then "Nillable " <> fieldTypeName
338− else fieldTypeName
339−
340− return $ Just $ mconcat
341− [ " "
342− , qualifier
343− , " \""
344− , fieldName
345− , "\" [t|"
346− , fieldType
347− , "|]"
348− ]
349−
350−makeQualifier :: (Int, Xsd.MaxOccurs) -> Gen Text
351−makeQualifier (minOcc, maxOcc) = case maxOcc of
352− Xsd.MaxOccursUnbound -> toQualifier minOcc maxBound
353− Xsd.MaxOccurs v -> toQualifier minOcc v
354−
355−toQualifier :: Int -> Int -> Gen Text
356−toQualifier 1 1 = return "!"
357−toQualifier 0 1 = return "?"
358−toQualifier 1 maxOcc
359− | maxOcc < 1
360− = genError "maxOccurs < minOccurs"
361−toQualifier 1 maxOcc
362− | maxOcc > 1
363− = return "+"
364−toQualifier _ _ = return "*"
365−
366−genUnsupported :: TypeName -> Gen ()
367−genUnsupported tn = do
368− let typeName = tnPrefixed tn
369− warn $ "generating stub for unsupported construct in " <> typeName
370− mode <- getMode
371− writeCode (makeComments tn [])
372− writeCode
373− [ "data " <> typeName <> " = " <> typeName
374− , " deriving (Eq, Show)"
375− , ""
376− , "instance NFData " <> typeName <> " where"
377− , " rnf _ = ()"
378− , ""
379− ]
380−
381− unless (mode == Parser) $ writeCode
382− [ "instance ToXML " <> typeName <> " where"
383− , " toXML _ = comment \"" <> typeName <> "\""
384− , ""
385− ]
386−
387− unless (mode == Generator) $ writeCode
388− [ "instance FromDom " <> typeName <> " where"
389− , " fromDom = undefined"
390− , ""
391− ]
392−
393−genHeader :: Options -> Gen ()
394−genHeader opts = do
395− case oHeader opts of
396− Nothing -> return ()
397− Just h -> do
398− writeCode . fmap ("-- " <>) . Text.lines $ h
399− writeCode [""]
400−
401− writeCode
402− [ "{-# OPTIONS_GHC -Wno-unused-imports #-}"
403− , "module " <> oModule opts <> " where"
404− , ""
405− , "import Control.DeepSeq"
406− , "import Data.Scientific"
407− , "import Data.THGen.XML"
408− ]
409− writeCode imports
410− writeCode
411− [ "import Prelude hiding ((*), (+))"
412− , ""
413− , ""
414− ]
415− where
416− imports = case oMode opts of
417− Generator -> [ xmlWriter, parentAttr ]
418− Parser -> [ domParser ]
419− ParserAndGenerator -> [ domParser, xmlWriter, parentAttr ]
420− xmlWriter = "import Text.XML.Writer"
421− parentAttr = "import Text.XML.ParentAttributes"
422− domParser = "import Text.XML.DOM.Parser"
423−
424−-- | We populate the initial state with all built-in types to make sure
425−-- they will be correctly resolved
426−initialGenState :: Options -> Map Xsd.QName Xsd.Type -> GenState
427−initialGenState opts types = GenState
428− { gsTypes = types
429− , gsExtensions = collectExtensions types
430− , gsKnownTypes = builtInTypes
431− , gsBoundTypeName = Set.empty
432− , gsBoundFields = Set.empty
433− , gsMode = oMode opts
434− , gsCode = []
435− , gsWarnings = []
436− }
437−
438−collectExtensions
439− :: Map Xsd.QName Xsd.Type
440− -> Map Xsd.QName [(Xsd.QName, Xsd.Type)]
441−collectExtensions = List.foldl' step Map.empty . Map.toList
442− where
443− step exts (n, t) = case baseOf t of
444− Nothing -> exts
445− Just base -> Map.insertWith (++) base [(n, t)] exts
446− baseOf (Xsd.TypeSimple _) = Nothing
447− baseOf (Xsd.TypeComplex t) = case Xsd.complexContent t of
448− Xsd.ContentComplex (Xsd.ComplexContentExtension e) ->
449− Just (Xsd.complexExtensionBase e)
450− _ -> Nothing
404+ xsd = case parseXSD def xml of
405+ Right xsd' -> xsd'
406+ Left e -> error $ show e
407+ T.hPutStrLn stdout $ generateIsoXml (read mode) xsd
src/Options.hsdeleted−84
@@ -1,84 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE TypeApplications #-}
3−
4−module Options
5− ( Options(..)
6− , optionsParser
7− , getOptions
8− , GenType(..)
9− , genTypeToText
10− , ModuleName
11− , Header
12− ) where
13−
14−import Data.Text (Text)
15−import qualified Data.Text as T
16−import Data.Version (showVersion)
17−import Options.Applicative
18−import Paths_xsd_isogen (version)
19−import Data.List
20−
21−
22−data GenType = Parser | Generator | ParserAndGenerator
23− deriving (Read, Show, Eq, Bounded, Enum)
24−
25−genTypeToText :: GenType -> Text
26−genTypeToText Parser = "Parser"
27−genTypeToText Generator = "Generator"
28−genTypeToText ParserAndGenerator = "ParserAndGenerator"
29−
30−type ModuleName = Text
31−type Header = Text
32−
33−data Options = Options
34− { oHeader :: Maybe Header
35− , oMode :: GenType
36− , oInput :: FilePath
37− , oModule :: ModuleName
38− }
39− deriving (Show)
40−
41−optionsParser :: Parser Options
42−optionsParser = Options
43− <$> ( flag' Nothing
44− ( long "no-header"
45− <> help "Do not place a header at the top of the file."
46− ) <|> Just <$> strOption
47− ( long "header"
48− <> help "A custom header to be placed at the top of the file."
49− <> value ("This file was generated by xsd-isogen version "
50− <> T.pack (showVersion version)
51− <> "\nhttps://github.com/dredozubov/xsd-isogen")
52− )
53− )
54− <*> option auto
55− ( long "mode"
56− <> short 'm'
57− <> value ParserAndGenerator
58− <> help ("Whether to generate both parsers and generators. One of: "
59− <> (mconcat . intersperse ", " . fmap show
60− $ [minBound @GenType .. maxBound]) <> ".")
61− )
62− <*> strOption
63− ( long "input"
64− <> short 'i'
65− <> help "Path to the input .xsd file."
66− )
67− <*> strOption
68− ( long "name"
69− <> short 'n'
70− <> help "Specify the name of the generated module."
71− <> value "Dummy"
72− )
73−
74−
75−getOptions :: IO Options
76−getOptions = execParser $ info (optionsParser <**> helper)
77− $ fullDesc
78− <> header
79− ( "xsd-isogen version " <> showVersion version
80− <> " (https://github.com/dredozubov/xsd-isogen)"
81− )
82− <> progDesc ( "A tool for generating xml-isogen-compatible "
83− <> "(https://github.com/typeable/xml-isogen) .hs files from .xsd files."
84− )
src/References.hsdeleted−80
@@ -1,80 +0,0 @@
1−
2−module References
3−( References(..)
4−)
5−where
6−
7−import qualified Xsd
8−
9−class References a where
10− references :: a -> [Xsd.QName]
11− referencesList :: [a] -> [Xsd.QName]
12− referencesList = concatMap references
13−
14−instance References t => References (Maybe t) where
15− references Nothing = []
16− references (Just t) = references t
17−
18−instance References Xsd.Type where
19− references (Xsd.TypeSimple t) = references t
20− references (Xsd.TypeComplex t) = references t
21−
22−instance References Xsd.SimpleType where
23− references (Xsd.AtomicType r _) = references r
24− references (Xsd.ListType r _) = references r
25− references (Xsd.UnionType rs _) = referencesList rs
26−
27−instance References Xsd.SimpleRestriction where
28− references r = references (Xsd.simpleRestrictionBase r)
29−
30−instance References Xsd.ComplexRestriction where
31− references r = [Xsd.complexRestrictionBase r]
32−
33−instance References t => References (Xsd.RefOr t) where
34− references (Xsd.Ref r) = [r]
35− references (Xsd.Inline t) = references t
36−
37−instance References Xsd.ComplexType where
38− references t = references (Xsd.complexContent t)
39−
40−instance References Xsd.Content where
41− references (Xsd.ContentComplex c) = references c
42− references (Xsd.ContentSimple c) = references c
43− references (Xsd.ContentPlain c) = references c
44−
45−instance References Xsd.PlainContent where
46− references t = referencesList (Xsd.plainContentAttributes t)
47− ++ references (Xsd.plainContentModel t)
48−
49−instance References Xsd.SimpleContent where
50− references _ = []
51−
52−instance References Xsd.ComplexContent where
53− references (Xsd.ComplexContentExtension e) = references e
54− references (Xsd.ComplexContentRestriction r) = references r
55−
56−instance References Xsd.ComplexExtension where
57− -- Note that we don't include extension base here
58− -- becase we don't depend on it. And actaully we generate extensions before
59− -- the base because we need to generate the ADT with all the extensions
60− -- at this point.
61− references e = referencesList (Xsd.complexExtensionAttributes e)
62− ++ references (Xsd.complexExtensionModel e)
63−
64−instance References Xsd.Attribute where
65− references (Xsd.RefAttribute a) = references a
66− references (Xsd.InlineAttribute a) = references a
67−
68−instance References Xsd.AttributeRef where
69− references a = [Xsd.attributeRefRef a]
70−
71−instance References Xsd.AttributeInline where
72− references = references . Xsd.attributeInlineType
73−
74−instance References Xsd.ModelGroup where
75− references (Xsd.Sequence elements) = referencesList elements
76− references (Xsd.Choice elements) = referencesList elements
77− references (Xsd.All elements) = referencesList elements
78−
79−instance References Xsd.Element where
80− references = references . Xsd.elementType
stack.yamldeleted−12
@@ -1,12 +0,0 @@
1−#resolver: nightly-2022-01-24
2−resolver: lts-18.23
3−
4−packages:
5−- .
6−
7−extra-deps:
8−- git: https://github.com/typeable/xsd-parser
9− commit: 648877d94d03a58dc9114f68d4e99c674e353fca
10−
11−nix:
12− packages: [zlib]
xsd-isogen.cabal+13−19
@@ -19,33 +19,27 @@ extra-source-files: CHANGELOG.md
1919
2020executable xsd-isogen
2121 main-is: Main.hs
22− other-modules: Options
23− , Gen
24− , BuiltInTypes
25− , References
26− , Paths_xsd_isogen
22+ -- other-modules:
2723 -- other-extensions:
28− build-depends: base >=4.12 && < 5.0
24+ build-depends: base ^>=4.12.0.0
2925 , bytestring
3026 , containers
3127 , data-default
32− , transformers
3328 , mtl
34− , optparse-applicative
3529 , text
36− , unordered-containers
3730 , writer-cps-mtl
3831 , xsd-parser
32+ , unordered-containers
3933 hs-source-dirs: src
4034 default-language: Haskell2010
4135 ghc-options: -fwarn-unused-binds
42− -fwarn-unused-imports
43− -Wall
44− -Wincomplete-uni-patterns
45− -Wincomplete-record-updates
46− -Wpartial-fields
47− -- -Werror=missing-home-modules
48− -Wmissing-home-modules
49− -Widentities
50− -Wredundant-constraints
51− -Wmissing-export-lists
36+ , -fwarn-unused-imports
37+ , -Wall
38+ , -Wincomplete-uni-patterns
39+ , -Wincomplete-record-updates
40+ , -Wpartial-fields
41+ , -Werror=missing-home-modules
42+ , -Wmissing-home-modules
43+ , -Widentities
44+ , -Wredundant-constraints
45+ , -Wmissing-export-lists