如何使用Haskell生成XML?

14ifxucb  于 2022-11-14  发布在  其他
关注(0)|答案(2)|浏览(134)

我正在寻找一种生成XML的方法,如下面的示例所示,但是现有的XML库没有提供足够的文档来帮助我理解如何使用它们来生成XML。我可以找到很多生成XML的库,但是没有一个库提供一个简单的示例:下面介绍如何生成这个XML。
例如,Blaze和Lucid库非常适合生成HTML。假设您要生成以下HTML:

<emph class="foo">bar</emph>

使用Lucid,您可以编写:

emph_ [class_ "foo"] "bar"

那么,用XML做这件事的好方法是什么呢?我一直在查找API文档,例如,HaXml。但是我找不到很多关于使用这些包的教程。
我确实看到Yesod's Hamlet quasi-quoter是一种非常简洁的生成XML的方法。但是我不喜欢准引用一个新模式的想法,因为它看起来不太容易维护,而且看起来像是在学习一门新语言。所以我希望找到一些更模块化、更可组合的东西,比如Blaze和Lucid。
编辑:进一步解释一下,问题不在于缺少Haskell XML库,也不在于知道使用哪一个。问题在于知道如何使用一个(其中的任何一个)生成XML。例如,我知道我可以使用Lucid的html_“foo”生成HTML代码<html>foo</html>。但我如何才能对XML做到这一点呢?
下面是一个我正在尝试做的伪 haskell 的例子:

目标:生成以下XML:

<foo attribute="something">
  <bar>
     <foobar>
        <barfoo>
           something here
        </barfoo>
     </foobar>
  </bar>
</foo>

伪 haskell :

foo_ [attribute_ "bar"] $ bar_ $ foobar_ $ barfoo_ "something here"
dgjrabp2

dgjrabp21#

在关于xml-hamlet的Yesod Book文档的开头,他们展示了如何使用xml-conduit API从xml-conduit生成XML。

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedLists #-}

import qualified Data.Text.Lazy.IO as Text
import qualified Data.Map as Map
import Text.XML

myFoo = Element "foo" [("attribute", "something")]
  [ NodeElement $ Element "bar" []
    [ NodeElement $ Element "foobar" []
      [ NodeElement $ Element "barfoo" []
        [ NodeContent "something here" ]]]]

main = Text.putStrLn $ renderText def $ Document (Prologue [] Nothing []) myFoo []

给出:

> main
<?xml version="1.0" encoding="UTF-8"?><foo attribute="something">
<bar><foobar><barfoo>something here</barfoo></foobar></bar></foo>

主要的问题是语法,但是使用简单的Haskell函数编写自己的类似于清晰的DSL并不困难。如果你想要一个完全灵活的语法,并且不依赖于模式,你可以编写:

-- helpers
attr_ = (,)
element_ nam attrs bdy = NodeElement $ Element nam (Map.fromList attrs) bdy
text_ = NodeContent

-- elements
foo_ = element_ "foo"
bar_ = element_ "bar"
foobar_ = element_ "foobar"
barfoo_ = element_ "barfoo_"

-- attributes
attribute_ = attr_ "attribute"

-- used to unwrap a top level Node to an Element
unNode (NodeElement x) = x

myFoo = unNode $
  foo_ [attribute_ "something"] $
    [ bar_ []
      [ foobar_ []
        [ barfoo_ []
          [ text_ "something here" ]]]]

main = Text.putStrLn $ renderText def $ Document (Prologue [] Nothing []) myFoo []

通常,语法可以通过考虑你的(非正式的)模式来简化。如果barfoo没有属性,只能包含一个文本块,那么你可以写:

barfoo_ txt = element_ "barfoo" [] [text_ txt]

并将其用作barfoo_ "something here"

92dk7w1h

92dk7w1h2#

我经常找不到足够的例子来轻松地开始使用新的Haskell库。
因此,虽然问答Which Haskell XML library to use?是从2009年和生态系统已经移动,答案可能是不一样的第一次检查,这个问答是第一次击中我时,谷歌“Haskell XML网站:stackoverflow.com“,所以它可能是值得修改的答案。(另外,还有一个选项可以关闭要求软件推荐的问题,这可能是因为答案既主观又随时间变化。)
如果我用search Hackage for "xml"并交叉引用这两个列表,看起来候选者大多数是相同的,而且似乎只有一个大的竞争者进入了,那就是xml-conduit。但是,与其根据它们的“DL”和更新的时间等来评估软件包(它们看起来有点相等),你可以依赖给出的答案:

  1. xml(如果任务很简单)
    在GitHub README中只有一个例子:
{-# LANGUAGE RecordWildCards #-}
import Text.XML.Light

data Package = Package
  { pOrderNo  :: String
  , pOrderPos :: String
  , pBarcode  :: String
  , pNumber   :: String
  }

-- | Create XML from a Package
instance Node Package where
  node qn Package {..} =
    node qn
      [ unode "package_number" pNumber
      , unode "package_barcode" pBarcode
      , unode "order_number" pOrderNo
      , unode "order_position" pOrderPos
      ]

我去找了一个使用xml库的库来做一个更好的例子。做一个reverse dependency search for "xml",你会得到一些类似大卫Himmelstrup的reanimate-svg的东西,它给我的印象可能是最近的,可能是一个很好的、简单的用法。这里,Graphics.SvgTree介绍了从字符串解析XML和将XML保存到文件中。Graphics.SvgTree.XmlParser涵盖了XML和某些数据类型之间的相互转换(在本例中,Document是SVG)。

相关问题