解析其他 XML 文件,同时使用 HXT 解析树

Parse other XML files whilst parsing tree with HXT

我正在解析 XML 描述游戏用户界面的文件,同时尝试学习 HXT。 我可以成功解析单个 XML 文件。但无法确定在 getWindow 函数内打开和解析其他 XML 文件的最佳方式是什么。

每个 XML 由 Window 个组成。每个 WindownamelibraryName。后者是描述 window 的 XML 文件的名称。 例如,根看起来像这样:

<!-- DOMDocument.xml -->
<elements>
    <Window libraryItemName="window_home" name="window_home">
    <!-- data here  -->
    </Window>
    <Window libraryItemName="window_battle" name="window_battle">
    <!-- data here  -->
    </Window>
</elements>

然后每个 window 都有一个单独的 XML 文件。例如。 "window_home":

<!-- window_home.xml -->
<elements>
    <Window libraryItemName="panel_tabs" name="panel_tabs" selected="true">
    <!-- data here  -->
    </Window>
    <Window libraryItemName="home_powerup_menu" name="home_powerup_menu" selected="true">
    <!-- data here  -->
    </Window>
    <Window libraryItemName="panel_name" name="panel_name" selected="true">
    <!-- data here  -->
    </Window>
</elements>

我用这段代码解析根 DOMDocument.xml

{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
import Text.XML.HXT.Core

parseXML = readDocument [ withValidate no
                        , withRemoveWS yes  -- throw away formating WS
                        ] 

atTag tag = deep (isElem >>> hasName tag)

data UiWindow = UiWindow {
    wndName :: String,
    wndNameLib :: String,
    wndChildren :: [UiWindow]
    } deriving (Show)

initUiWindow = UiWindow {
    wndName = "empty",
    wndNameLib = "",
    wndChildren = []
    }


getWindow = atTag "Window" >>> 
  proc x -> do
    _libraryItemName <- getAttrValue "libraryItemName" -< x
    _name <- getAttrValue "name" -< x
    -- TODO: Open _libraryItemName XML file and parse windows in it
    returnA -< initUiWindow { wndName = _name, wndNameLib = _libraryItemName}

documentName = "DOMDocument.xml"        

parseRoot = parseXML documentName
--runX (parseRoot >>> getWindow )

由于 getWindow 函数未包含在 IO 中,因此实现所需行为的最佳方法是什么?

HXT 组合器是多态的,并且有一种类型 IOLA which implements all the XML parsing-relevant typeclasses, in addition to ArrowIO 可以执行 IO 中箭头。

例如,如果你想对文件进行完全递归解析,你可以做一些简单的事情

parseDoc docName = runX $ parseXML fileName >>> getWindow
  where
    fileName = docName ++ ".xml"

getWindow = atTag "Window" >>> proc x -> do
    libraryItemName <- getAttrValue "libraryItemName" -< x
    name <- getAttrValue "name" -< x
    children <- arrIO parseDoc -< libraryItemName
    returnA -< initUiWindow { wndName = name, wndNameLib = libraryItemName, wndChildren = children}