How to access some XML data with Haskell (using HaXml)?
I want to get access to the data of an XML file like
<?xml version="1.0"?>
<MY>
<Foo id="1" name="test">
<Argument name="a" />
</Foo>
<Foo id="2" name="test2">
<Argument name="a" 开发者_JAVA百科/>
<Argument name="b" />
</Foo>
<Other id="2" name="someOther"/>
</MY>
I want e.g. to read out each Foo with its Arguments, how can I do this with Haskell? (I would like to use the HaXml module)
I don't know where to start.
For simple tasks you might want to consider the tagsoup package.
Yes, documentation is a big cons about haskell. I wonder why haskell people hate documenting their code so much. No need for fat papers, few usage examples is usually more than enough.
Also small example of HaXML usage available here: http://book.realworldhaskell.org/read/extended-example-web-client-programming.html
I cannot find up to date documentation and examples for haXml.
There is however some documentation for HXT available. I know that's probably an overkill for your example, but anyway.
If you want to use tagsoup, perhaps the following answers might help:
xml-tree parser (Haskell) for graph-library
In Haskell how do you extract strings from an XML document?
Here is the documentation an examples for HXT:
http://www.haskell.org/haskellwiki/HXT/Conversion_of_Haskell_data_from/to_XML
http://www.haskell.org/haskellwiki/HXT
http://www.haskell.org/haskellwiki/HXT/Practical
http://en.wikibooks.org/wiki/Haskell/XML
Now the code using HXT. (warning I am not sure if this is the correct way)
I followed the tutorial: http://www.haskell.org/haskellwiki/HXT/Conversion_of_Haskell_data_from/to_XML
you need your xml file as "data.xml"
import Data.Map (Map, fromList, toList)
import Text.XML.HXT.Core
type Foos = Map String [Foo]
data Foo = Foo
{
fooId :: String
, fooName :: String
, arguments :: [Argument]
}
deriving (Show, Eq)
data Argument = Argument
{ argName :: String
}
deriving (Show, Eq)
instance XmlPickler Foo where
xpickle = xpFoo
instance XmlPickler Argument where
xpickle = xpArgument
-- WHY do we need this?? no clue
instance XmlPickler Char where
xpickle = xpPrim
-- this could be wrong
xpFoos :: PU Foos
xpFoos
= xpWrap (fromList
, toList
) $
xpList $
xpElem "MY" $
xpickle
xpFoo :: PU Foo
xpFoo
= xpElem "Foo" $
xpWrap ( uncurry3 Foo
, \ f -> (fooId f
, fooName f
, arguments f
)
) $
xpTriple (xpAttr "id" xpText)
(xpAttr "name" xpText)
(xpList xpickle)
xpArgument :: PU Argument
xpArgument
= xpElem "Argument" $
xpWrap ( \ ((a)) -> Argument a
, \ t -> (argName t)
) $
(xpAttr "name" xpText )
main :: IO ()
main
= do
runX ( xunpickleDocument xpFoos
[ withValidate no
, withTrace 1
, withRemoveWS yes
, withPreserveComment no
] "data.xml"
>>>
arrIO ( \ x -> do {print x ; return x})
)
return ()
RESULT (you need you xml example as "data.xml"):
-- (1) getXmlContents
-- (1) readDocument: "data.xml" (mime type: "text/xml" ) will be processed
-- (1) readDocument: "data.xml" processed
fromList [("",[Foo {fooId = "1", fooName = "test", arguments = [Argument {argName = "a"}]},
Foo {fooId = "2", fooName = "test2", arguments = [Argument {argName = "a"},
Argument {argName = "b"}]}])]
With xml-conduit you can do it very simple and straightforward:
{-# LANGUAGE OverloadedStrings #-}
import Data.Conduit
import qualified Text.XML.Stream.Parse as XP
import Data.String(fromString)
parseFile fileName = runResourceT $ XP.parseFile XP.def (fromString fn)
$$ parseXML
parseXML = XP.force $ XP.tagNoAttr "MY"
$ XP.many
$ XP.tagName "foo" (mapM XP.requiredAttr ["id", "name"])
$ \(~[i,n]) -> return (i,n)
There is a tutorial introduction to haxml, my answer comes a little late, but I think the tutorial describes how to parse a XML very similar to the one you provided in your question.
A very simplistic implementation of how to read the XML would be:
c <- fReadXml "your.xml" :: IO ANYContent
print c
精彩评论