2016-03-08 109 views
0

這個問題是關於如何使用xmlns屬性等解析xml內容。我寫了代碼來解析它的工作原理。我會很感激能否做得更好的指針。用XML解析名稱空間的元素

我有如下一個XML文件test.xml

{-# LANGUAGE OverloadedStrings #-} 
import Prelude hiding (readFile) 
import Text.XML 
import Text.XML.Cursor 
import qualified Data.Text as T 
import Data.Text.Lazy.Builder (toLazyText) 
import Data.Text.Lazy (fromStrict) 

main :: IO() 
main = do 
    doc <- readFile def "test.xml" 
    let cursor = fromDocument doc 
     res = fromStrict $ T.concat $ child cursor >>= laxElement "Body" >>= child >>= laxElement "SomeResponse" >>= child >>= laxElement "SomeResult" >>= descendant >>= content 
     pres = parseText_ def res 
     cursor2 = fromDocument pres 
     res2 = child cursor2 >>= element "head" >>= child >>= element "title" >>= descendant >>= content 
    print $ res2 

產出ghci

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body> 
<SomeResponse xmlns="https://testsomestuff.org/API/WS/"> 
<SomeResult> 
&lt;html&gt; 
    &lt;head&gt; 
     &lt;title&gt;My &lt;b&gt;Title&lt;/b&gt;&lt;/title&gt; 
    &lt;/head&gt; 
    &lt;body&gt; 
     &lt;p&gt;Foo bar baz&lt;/p&gt; 
    &lt;/body&gt; 
&lt;/html&gt; 
</SomeResult> 
</SomeResponse> 
</soap:Body></soap:Envelope> 

我使用xml-conduit寫的代碼來解析 「SomeResult」 內容解析正確:

*Main> main 
["My ","Title"] 

laxElement應用程序蟑螂找到SomeResult內容的好方法嗎?如果有更好的方法,我會非常感謝這方面的指針。

此外,我需要做相反方向的HTTP編碼(當建立一個上面的響應請求時)內部身體被轉義的地方(如SomeResulttext.xml)。當使用Text.XML構建請求時,默認情況下是否需要處理這些內容,或者是否必須通過使用類似html-entities的內容來明確地將內部體轉換爲轉義http?加上xml-conduit

回答

1

,我建議使用一個微小的「鏡頭」包,如xml-html-conduit-lensxml-lens(兩者十分相似,但我選擇了在源快速瀏覽後的第一個)。命名空間支持(請參閱this issue

如果您需要更具體的示例,可以查看one of my experimental project。從該項目,這裏是一個遍歷獲取特定機器從VCLOUD API的信息:

fetchVM :: AsXmlDocument t => Text -> Traversal' t Element 
fetchVM n = xml...ovfNode "VirtualSystem".attributed (ix (nsName ovfNS "id").only n) 

然後您可以結合遍歷as such

vmId = raw ^. responseBody . fetchVM vmName . fetchVmId.text 

看看如何ovhNodensName定義看我如何處理命名空間。

這裏是關於主題的另一個有趣的文章: https://www.schoolofhaskell.com/user/chad/snippets/random-code-snippets/xml-conduit-lens

另一個技巧是堅持「XML的導管」(至少現在)。有人建議taggy作爲替代品,但不幸的是,它目前不在積極的開發週期(見https://github.com/alpmestan/taggy/issues/14

我希望它有幫助。