我正在解析描述游戏用户界面的XML文件,并尝试同时学习HXT。
我可以成功解析单个XML文件。但无法确定在getWindow
函数内部打开和解析其他XML文件的最佳方法。
每个XML由Window
个数组成。每个Window
都有name
和libraryName
。后者是描述窗口的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
内,因此实现所需行为的最佳方法是什么?
答案 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}