2009-03-17 13 views
7

Ben bir XML böyle bir belge varsa:Haskell'de bir XML belgesinden dizeleri nasıl ayıklarsınız?

<root> 
    <elem name="Greeting"> 
    Hello 
    </elem> 
    <elem name="Name"> 
    Name 
    </elem> 
</root> 

ve bunun gibi bazı Haskell tipi/veri tanımlarını:

type Name = String 
type Value = String 
data LocalizedString = LS Name Value 

ve aşağıdaki imzası ile bir Haskell işlevi yazmak istedim:

birinci parametre, XML metin ve döndürülen değer oldu
getLocalizedStrings :: String -> [LocalizedString] 

oldu:

[LS "Greeting" "Hello", LS "Name" "Name"] 

bunu nasıl yapardınız? HaXml iyi araç ise

, nasıl HaXml yukarıdaki hedefe ulaşmak için kullanırdınız?

Teşekkür ederiz!

cevap

5

Aslında HaXML kullanarak XML belgelerinin dışarı bit ayıklamak için anlamaya rahatsız olmamıştım; HXT tüm ihtiyaçlarımı karşıladı.

{-# LANGUAGE Arrows #-} 
import Data.Maybe 
import Text.XML.HXT.Arrow 

type Name = String 
type Value = String 
data LocalizedString = LS Name Value 

getLocalizedStrings :: String -> Maybe [LocalizedString] 
getLocalizedStrings = (.) listToMaybe . runLA $ xread >>> getRoot 

atTag :: ArrowXml a => String -> a XmlTree XmlTree 
atTag tag = deep $ isElem >>> hasName tag 

getRoot :: ArrowXml a => a XmlTree [LocalizedString] 
getRoot = atTag "root" >>> listA getElem 

getElem :: ArrowXml a => a XmlTree LocalizedString 
getElem = atTag "elem" >>> proc x -> do 
    name <- getAttrValue "name" -< x 
    value <- getChildren >>> getText -< x 
    returnA -< LS name value 

Sen ediyorum muhtemelen biraz daha fazla hata denetimi gibi (yani sadece tembel benim gibi atTag kullanmayın; aslında <elem> soyundan vb olduğunu <root> kök olduğunu doğrulamak) ama bu sadece çalışıyor örneğiniz üzerine. Eğer Arrow s bir giriş gerekiyorsa


Şimdi, ne yazık ki her iyi birinin bilmiyorum. Ben kendimi "nasıl yüzüleceğini öğrenmek için okyanusa atılmış" şekilde öğrendim. akılda tutmak yararlı olabilir

şey proc/-< sözdizimi sadece do/<- gibi basitçe temel ok işlemleri (arr, >>> vs.) için şeker olduğunu temel monad işlemleri için basitçe şeker olduğunu (return, >>=, vb.). Aşağıdaki eşdeğerdir:

getAttrValue "name" &&& (getChildren >>> getText) >>^ uncurry LS 

proc x -> do 
    name <- getAttrValue "name" -< x 
    value <- getChildren >>> getText -< x 
    returnA -< LS name value 
+0

size çok bilgilendirici cevap için çok teşekkür ederim! –

+0

http://www.haskell.org/haskellwiki/HXT adresinde bir HXT öğreticisi var, ama bu hiç durmadan bir noktadan ibarettir, bu yüzden bunun ok do-notasyonu ile nasıl ilişkili olduğunu anlamak (yukarıdaki örnekte olduğu gibi) kolay değildir . –

2

FWIW, HXT TagSoup ile basit TagSoup İşte benim ikinci denemesi (başkalarının bazı iyi girdi aldıktan sonra) var :)

1

yapacak overkill gibi görünüyor:

ilk girişim bir dizenin kapalı boşluk kırparak için naif (ve arızalı) yöntemini görücüye.

+0

TagSoup, hatalı biçimlendirilmiş girişi kabul eder - ki gerçekten hoşunuza gidebilir :) - ne yazık ki IMO'nun bu çözümü okumak daha zordur. Minor nit: "trimWhiteSpace = dropWhile isSpace" gibi bir şey daha fazlasını beklerdim. ters . dropWhile isSpace. reverse'; Seninki daha çok "removeAllWhiteSpace" gibi. – ephemient

+0

Teşekkürler ephemient. Daha iyi örnek veriler almalıydım. :) XML'imde gömülü bazı yeni satırlar olduğu içinSpace'in yeni satırlardan kurtulduğundan emin olmalıyım. –

+0

Sadece kendiniz deneyin: GHCi'ye 'Data.Char.isSpace '\ n'' yazın. Evet, yeni satırlar her zaman ve her yerdeydi. Benim nit'm, 'trimWhiteSpace' inizin satırları boyunca, benim için sezgisel olmayan bir b c "==" abc "' si ile ilgili değildi. Ya da belki ben garipim. – ephemient

3

Kullanım XML paketlerinden biri.

en popüler

  1. haxml, sırayla, şunlardır
  2. hxt
  3. xml ışık
  4. hexpat
İlgili konular