File: Xml.hs

package info (click to toggle)
hugs98 98.200311-4
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 12,964 kB
  • ctags: 8,084
  • sloc: ansic: 67,521; haskell: 61,497; xml: 4,566; sh: 3,264; cpp: 1,936; yacc: 1,094; makefile: 915; cs: 883; sed: 10
file content (96 lines) | stat: -rw-r--r-- 2,898 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
--
-- External parsing of XML documents
--
module Xml where

import Dotnet
import qualified Dotnet.System.Xml.XmlDocument
import Dotnet.System.Xml.XmlNode
import Dotnet.System.Xml.XmlNodeType as Type
import Dotnet.System.Xml.XmlNodeList
import qualified Dotnet.System.Xml.XmlAttributeCollection as Attr
import qualified Dotnet.System.Xml.XmlNamedNodeMap as Attr
import qualified Dotnet.System.Xml.XmlAttribute as At
import qualified Dotnet.System.Xml.XmlDeclaration as Decl
import XMLSyn
import Maybe

--
-- This example demonstrates how to make use of the .NET Xml classes
-- to handle the parsing of XML documents. After having parsed a document
-- externally, we simply walk over the document to generate a Haskell
-- representation of it.
--

loadXML :: String -> IO XMLDoc
loadXML url = do
  doc <- newDoc
  doc # Dotnet.System.Xml.XmlDocument.load_3 url
  l   <- doc # get_FirstChild
  tag <- doc # get_NodeType
  let v = Type.fromXmlNodeType tag
  case v of
    Type.Document -> do
      version <- doc # getVersion
      vs <- doc # getNodes
      return (XMLDoc version vs)
    _ -> return (XMLDoc Nothing [])

getVersion :: XmlNode a -> IO (Maybe XMLHeader)
getVersion doc = do
  -- probe for the xml declaration (assumed to be first child of a document.)
  ch  <- doc # get_FirstChild
  tag <- ch # get_NodeType
  case Type.fromXmlNodeType tag of
    Type.XmlDeclaration -> do
      v   <- ch # Decl.get_Version
      enc <- ch # Decl.get_Encoding
      std <- ch # Decl.get_Standalone
      return (Just (XMLHeader (Just (XMLVersionInfo v (Just enc) (Just std))) [] []))
    _ -> return Nothing

getNodes :: XmlNode a -> IO [Markup]
getNodes node = do
      ls <- node # get_ChildNodes
      c  <- ls   # get_Count
      vs <- mapM (\ i -> ls # item i >>= \ obj -> getNode obj) [0..(c-1)]
      return (catMaybes vs)

getNode :: XmlNode a -> IO (Maybe Markup)
getNode node = do
  tag <- node # get_NodeType
  let v = Type.fromXmlNodeType tag
  case v of
    Type.Element -> do
      s  <- node # get_Name
      vs <- node # getNodes
      as <- node # getAttributes
      return (Just (XMLSyn.Element (Elem s as (Just vs))))
    Type.Comment -> do
      s <- node # get_InnerText
      return (Just (XMLSyn.Comment s))
    Type.Text -> do
      s <- node # get_InnerText
      return (Just (XMLSyn.CharData s))
    _ ->
{- debugging:
      str <- toString tag
      print str
-} 
      return Nothing

getAttributes :: XmlNode a -> IO [Attribute]
getAttributes node = do
  as <- node # get_Attributes
  c  <- as # Attr.get_Count
  mapM (\ i -> as # Attr.item i >>= \ obj -> getAttribute obj) [0..(c-1)]
  
getAttribute :: At.XmlAttribute a -> IO Attribute
getAttribute attr = do
  x <- attr # At.get_LocalName
  y <- attr # At.get_Value
  return (XMLSyn.Attribute x y)

foreign import dotnet
  "ctor System.Xml.XmlDocument"
  newDoc :: IO (Dotnet.System.Xml.XmlDocument.XmlDocument ())