2010-10-09 17 views
5

Tôi đang cố gắng tìm đường qua HXT với XPath và các mũi tên cùng một lúc và tôi hoàn toàn bị mắc kẹt về cách suy nghĩ thông qua vấn đề này. Tôi có HTML sau:Haskell HXT để trích xuất danh sách các giá trị

<div> 
<div class="c1">a</div> 
<div class="c2">b</div> 
<div class="c3">123</div> 
<div class="c4">234</div> 
</div> 

mà tôi đã trích xuất thành HXT XmlTree. Những gì tôi muốn làm là xác định một chức năng (tôi nghĩ?):

getValues :: [String] -> IOSArrow Xmltree [(String, String)] 

nào, nếu được sử dụng như getValues ["c1", "c2", "c3", "c4"], sẽ làm cho tôi:

[("c1", "a"), ("c2", "b"), ("c3", "123"), ("c4", "234")] 

Trợ giúp xin vui lòng?

Trả lời

2

Dưới đây là một cách tiếp cận (loại của tôi là một chút tổng quát hơn và tôi không sử dụng XPath):

{-# LANGUAGE Arrows #-} 
module Main where 

import qualified Data.Map as M 
import Text.XML.HXT.Arrow 

classes :: (ArrowXml a) => a XmlTree (M.Map String String) 
classes = listA (divs >>> divs >>> pairs) >>> arr M.fromList 
    where 
    divs = getChildren >>> hasName "div" 
    pairs = proc div -> do 
     cls <- getAttrValue "class" -< div 
     val <- deep getText   -< div 
     returnA -< (cls, val) 

getValues :: (ArrowXml a) => [String] -> a XmlTree [(String, Maybe String)] 
getValues cs = classes >>> arr (zip cs . lookupValues cs) 
    where lookupValues cs m = map (flip M.lookup m) cs 

main = do 
    let xml = "<div><div class='c1'>a</div><div class='c2'>b</div>\ 
      \<div class='c3'>123</div><div class='c4'>234</div></div>" 

    print =<< runX (readString [] xml >>> getValues ["c1", "c2", "c3", "c4"]) 

tôi có lẽ sẽ chạy một mũi tên để có được bản đồ và sau đó thực hiện tra cứu, nhưng theo cách này cũng vậy.


Để trả lời câu hỏi của bạn về listA: divs >>> divs >>> pairs là danh sách mũi tên với loại a XmlTree (String, String) -i.e., đó là một tính toán không xác định mà phải mất một cây XML và trả về cặp chuỗi.

arr M.fromList có loại a [(String, String)] (M.Map String String). Điều này có nghĩa là chúng tôi không thể chỉ soạn nó với divs >>> divs >>> pairs, vì các loại không khớp.

listA giải quyết vấn đề này: nó sụp đổdivs >>> divs >>> pairs vào một phiên bản xác định với loại a XmlTree [(String, String)], đó là chính xác những gì chúng ta cần.

+0

Danh sáchA làm gì? – Muchin

0

Dưới đây là một cách để làm điều đó bằng HandsomeSoup:

-- For the join function. 
import Data.String.Utils 
import Text.HandsomeSoup 
import Text.XML.HXT.Core 

-- Of each element, get class attribute and text. 
getItem = (this ! "class" &&& (this /> getText)) 
getItems selectors = css (join "," selectors) >>> getItem 

main = do 
    let selectors = [".c1", ".c2", ".c3", ".c4"] 
    items <- runX (readDocument [] "data.html" >>> getItems selectors) 
    print items 

data.html là file HTML.