2010-10-09 14 views
5

Estoy tratando de abrirme camino a través de HXT con XPath y flechas al mismo tiempo y estoy completamente atascado en cómo pensar en este problema. Tengo el siguiente código HTML:Haskell HXT para extraer una lista de valores

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

que he extraído en un HXT XmlTree. Lo que me gustaría hacer es definir una función (creo?):

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

Lo cual, si se utiliza como getValues ["c1", "c2", "c3", "c4"], me va a obtener:

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

Ayuda por favor?

Respuesta

2

Aquí es un enfoque (mis tipos son un poco más general y no estoy usando 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"]) 

que probablemente ejecutar una flecha para conseguir el mapa y luego hacer las operaciones de búsqueda, pero de esta manera funciona también


Para responder a su pregunta sobre listA: divs >>> divs >>> pairs es una flecha de la lista con el tipo a XmlTree (String, String) -i.e., es un cómputo no determinista que tiene un árbol XML y devuelve pares de cadenas.

tiene a [(String, String)] (M.Map String String). Esto significa que no podemos simplemente componerlo con divs >>> divs >>> pairs, ya que los tipos no coinciden.

listA resuelve este problema: se derrumba divs >>> divs >>> pairs en una versión determinista con el tipo a XmlTree [(String, String)], que es exactamente lo que necesitamos.

+0

¿Qué hace la listaA? – Muchin

0

Aquí es una manera de hacerlo utilizando 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 es el archivo HTML.

Cuestiones relacionadas