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

时间:2015-12-22 13:26:59

标签: xml haskell hxt io-monad

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

每个XML由Window个数组成。每个Window都有namelibraryName。后者是描述窗口的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>

然后每个窗口都有一个单独的XML文件。例如。 &#34; window_home&#34;:

<!-- 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内,因此实现所需行为的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

HXT组合器是多态的,并且有IOLA类型实现了所有与XML解析相关的类型类,除了ArrowIO之外,它可以实现IO mid-箭头。

例如,如果要对文件进行完全递归的解析,可以执行简单的操作

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}