@@ -2,13 +2,81 @@ module Text.XSD.Parser where
3import Control.Exception
3import Control.Exception
4import Control.Monad
4import Control.Monad
5+import Control.Monad.Error
6+import Control.Monad.Trans.Reader
5import Data.ByteString.Lazy
7import Data.ByteString.Lazy
6−import Text.XML
8+import Data.Map as M
11+import Text.XML as XML
12+import Text.XML.Cursor as XML
7import Text.XSD.Internal as XSD
13import Text.XSD.Internal as XSD
10−toXsd :: Document -> Either SomeException XSD.Element
16+newtype XSDException = XSDException String
11−toXsd = undefined
17+ deriving (Show)
19+instance Exception XSDException
21+type XSDMonad a = ReaderT (M.Map Name Datatype) (Either SomeException) a
13parseXSD :: ParseSettings -> ByteString -> Either SomeException XSD.Element
23parseXSD :: ParseSettings -> ByteString -> Either SomeException XSD.Element
14−parseXSD ps bs = toXsd =<< parseLBS ps bs
24+parseXSD ps bs = parseLBS ps bs >>= toXsd
28+ | Expectation :+: Expectation
30+satisfy :: Expectation -> XML.Node -> Bool
31+satisfy exp node@(NodeElement (XML.Element name _ _)) =
33+ NodeElement (XML.Element (Name name _ _) _ _) -> case exp of
34+ ExpName n -> name == n
35+ exp1 :+: exp2 -> satisfy exp1 node && satisfy exp2 node
41+satisfySome c e = satisfySome' True c e
44+ :: Bool -- ^ check current
48+satisfySome' checkCurrent cur [] = True
49+satisfySome' checkCurrent cur (exp:exps) = result
51+ satisfyCurrent = satisfy exp (node cur)
52+ validChildren = P.filter (satisfy (P.head exps) . node) (child cur)
54+ if checkCurrent && P.null exps
56+ else P.foldr (\c r -> r && satisfySome' False c exps) True validChildren
59+throwXsd :: Show s => s -> XSDMonad a
60+throwXsd = throwError . SomeException . XSDException . show
62+toSchema :: XML.Node -> [XSD.Element] -> XSDMonad XSD
63+toSchema (XML.NodeElement (XML.Element (Name name _ _) _ _)) elems
64+ | name == "schema" = pure $ XSD $ XSD.Element (XSSeq []) "schema" [] elems
65+ | otherwise = throwXsd "Top-level schema definition not found"
67+fromElem :: XML.Cursor -> XSDMonad XSD.Element
70+ NodeElement el -> case nameLocalName (elementName el) of
73+ "simpleType" -> error "TODO: implement"
75+ throwXsd $ "xsd node not supported: " <> show e
77+toXsd :: Document -> Either SomeException XSD.Element
80+ cursor = fromDocument doc
81+ elems = child cursor &| fromElem
82+ runReader M.null $ toSchema (node cursor) elems