2014-05-01 56 views
1

我正在嘗試使用xml-conduit和xml-lens來解析和遍歷XML文檔。而不是必須多次遍歷文檔的相同部分,我想將遍歷存儲到前一個點,然後進一步向下鑽取。用鏡頭保存位置

ex。

let pos = doc ^. root . el "foo" 
    bar = pos . text 
    baz = pos ./ el "quux" . text 

當我嘗試這樣做,我得到以下錯誤:

No instance for (Data.Monoid.Monoid Element) 
    arising from a use of `el' 
Possible fix: 
    add an instance declaration for (Data.Monoid.Monoid Element) 
In the second argument of `(.)', namely `el "foo"' 
In the second argument of `(^.)', namely `root . el "foo"' 
In the expression: doc ^. root . el "foo" 

我能做些什麼來存儲這些中間位置?

回答

1

發生此類型錯誤的原因是elTraversal。遍歷指向多個值(在這種情況下,所有foo元素)。另一方面,(^.)總是返回單個值。使用(^.)Traversal僅適用於目標類型爲Monoid;在這種情況下,使用mappend將多個值砸成一個值。但是,Element不是Monoid(因爲沒有將XML元素組合到單個元素中的明智方式),因此(^.)不起作用。要獲得匹配的XML元素,您應該使用(^..)來代替,這會將它們作爲列表返回。

至於正確的問題(「我能做些什麼來存儲這個中間位置?」),Traversal是對位置的引用,所以如果你想進一步撰寫它,你不想「解除引用」它與(^.)(^..)。以下應該工作:

let pos = root . el "foo" 
    baz = pos ./ el "quux" . text 
    elemTexts = doc ^.. baz 
+0

感謝您對錯誤的解釋。如果我需要多次使用相同的位置,每次都不需要遍歷文檔,因爲我基本上只是節省了如何遍歷該位置,但實際上並沒有這樣做。 – Adam

+0

@Adam是的,如果你重複使用'pos'和'baz'。如果您擔心可以從'baz'中刪除'text'遍歷並重用'elms = doc^.. baz',那麼這將成爲(已經被解除引用的)元素列表。 – duplode

+0

如果我使用'(^ ..)'來獲取元素列表,那麼列表可以被重新轉換爲'Traversal'',這樣我就可以在其後的xml-lens中使用其他函數? – Adam