Haskell/XML
外觀
< Haskell
有幾個用於 XML 工作的 Haskell 庫,以及一些用於 HTML 的額外庫。對於更多與 Web 相關的作品,你可能想參考 Haskell/Web 程式設計 章節。
- Haskell XML 工具箱 (hxt) 是一組用於解析 XML 的工具,旨在比其他工具採用更通用的方法。
- HaXml 是一組用於使用 Haskell 解析、過濾、轉換和生成 XML 文件的實用程式。
- HXML 是一種非驗證、惰性、空間效率高的解析器,可以用作 HaXml 的直接替換。
- xml-conduit 提供用於 XML 的解析和渲染功能。有關教程,請參見 [1]。
- HSXML 將 XML 文件表示為靜態型別安全的 s 表示式。
- tagsoup 是一個用於解析非結構化 HTML 的庫,即它不假設資料的有效性或良好格式。
在下文中,我們將使用 Haskell XML 工具箱作為我們的示例。你應該有一個工作正常的 GHC 安裝,包括 GHCi,並且你應該根據 說明 下載並安裝 HXT。
有了這些,我們就可以開始使用 HXT 了。讓我們將 XML 解析器引入作用域,並解析一個簡單的 XML 格式字串
Prelude> :m + Text.XML.HXT.Parser.XmlParsec
Prelude Text.XML.HXT.Parser.XmlParsec> xread "<foo>abc<bar/>def</foo>"
[NTree (XTag (QN {namePrefix = "", localPart = "foo", namespaceUri = ""}) [])
[NTree (XText "abc") [],NTree (XTag (QN {namePrefix = "", localPart = "bar",
namespaceUri = ""}) []) [],NTree (XText "def") []]]
我們看到 HXT 將 XML 文件表示為樹列表,其中節點可以構造為包含子樹列表的 XTag,或包含字串的 XText。使用 GHCi,我們可以更詳細地探索這一點
Prelude> :m + Data.Tree.NTree.TypeDefs
Prelude Text.XML.HXT.Parser.XmlParsec Text.XML.HXT.DOM> :i NTree
data NTree a = NTree a (NTrees a)
-- Defined in Data.Tree.NTree.TypeDefs
Prelude Text.XML.HXT.Parser.XmlParsec Text.XML.HXT.DOM> :i NTrees
type NTrees a = [NTree a] -- Defined in Data.Tree.NTree.TypeDefs
正如我們所見,NTree 是一種通用的樹結構,其中節點在其列表中儲存其子節點,並且更多瀏覽將告訴我們 XML 文件是基於 XNode 型別的樹,定義為
data XNode = XText String | XCharRef Int | XEntityRef String | XCmt String | XCdata String | XPi QName XmlTrees | XTag QName XmlTrees | XDTD DTDElem Attributes | XAttr QName | XError Int String
回到我們的示例,我們注意到雖然 HXT 成功解析了我們的輸入,但人們可能希望為人類消費提供更清晰的表示。幸運的是,DOM 模組提供了這一點。請注意,xread 返回一個樹列表,而格式化函式作用於單個樹。
Prelude Text.XML.HXT.Parser.XmlParsec> :m + Text.XML.HXT.DOM.FormatXmlTree
Prelude Text.XML.HXT.Parser.XmlParsec Text.XML.HXT.DOM> putStrLn $ formatXmlTree $ head $ xread "<foo>abc<bar/>def</foo>"
---XTag "foo"
|
+---XText "abc"
|
+---XTag "bar"
|
+---XText "def"
這種表示使結構變得明顯,並且很容易看到它與我們的輸入字串的關係。讓我們繼續用一些屬性擴充套件我們的 XML 文件(當然要小心地轉義引號)
Prelude Text.XML.HXT.Parser.XmlParsec> xread "<foo a1=\"my\" b2=\"oh\">abc<bar/>def</foo>"
[NTree (XTag (QN {namePrefix = "", localPart = "foo", namespaceUri = ""}) [NTree (XAttr (QN
{namePrefix = "", localPart = "a1", namespaceUri = ""})) [NTree (XText "my") []],NTree (XAttr
(QN {namePrefix = "", localPart = "b2", namespaceUri = ""})) [NTree (XText "oh") []]]) [NTree
(XText "abc") [],NTree (XTag (QN {namePrefix = "", localPart = "bar", namespaceUri = ""}) [])
[],NTree (XText "def") []]]
請注意,屬性作為具有 XAttr 內容型別的常規 NTree 節點儲存,並且(當然)沒有子節點。隨意像上面那樣對該表示式進行美化列印。
對於資料提取的簡單示例,請考慮使用 XPath 的這個小示例
Prelude> :set prompt "> "
> :m + Text.XML.HXT.Parser.XmlParsec Text.XML.HXT.XPath.XPathEval
> let xml = "<foo><a>A</a><c>C</c></foo>"
> let xmltree = head $ xread xml
> let result = getXPath "//a" xmltree
> result
> [NTree (XTag (QN {namePrefix = "", localPart = "a", namespaceUri = ""}) []) [NTree (XText "A") []]]
> :t result
> result :: NTrees XNode