В Haskell, как вы извлекаете строки из XML-документа? - PullRequest
7 голосов
/ 17 марта 2009

Если у меня есть XML-документ, подобный этому:

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

и некоторые определения типа / данных на Haskell, например:

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

и я хотел написать функцию на Haskell со следующей подписью:

 getLocalizedStrings :: String -> [LocalizedString]

где первым параметром был текст XML, а возвращаемым значением было:

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

как бы я это сделал?

Если HaXml - лучший инструмент, как бы я использовал HaXml для достижения вышеуказанной цели?

Спасибо!

Ответы [ 4 ]

6 голосов
/ 17 марта 2009

Я никогда не задумывался над тем, как извлечь биты из документов XML, используя HaXML ; HXT удовлетворил все мои потребности.

{-# 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

Вы, вероятно, хотели бы немного больше проверять ошибки (т.е. не просто лениво использовать atTag, как я; на самом деле убедитесь, что <root> является root, <elem> является прямым потомком и т. Д.), Но это работает просто отлично на вашем примере.


Теперь, если вам нужно введение в Arrow s, к сожалению, я не знаю ни одного хорошего. Я сам научился этому «брошен в океан, чтобы научиться плавать».

Следует помнить, что синтаксис proc / -< является просто сахаром для базовых операций со стрелками (arr, >>> и т. Д.), Как и do / <- - просто сахар для основных монадных операций (return, >>= и т. Д.). Следующее эквивалентно:

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

proc x -> do
    name <- getAttrValue "name" -< x
    value <- getChildren >>> getText -< x
    returnA -< LS name value
3 голосов
/ 27 марта 2009

Используйте один из пакетов XML.

Наиболее популярны, по порядку,

  1. haxml
  2. HXT
  3. XML-свет
  4. hexpat
2 голосов
/ 18 марта 2009

FWIW, HXT кажется излишним, когда простой TagSoup сделает:)

1 голос
/ 18 марта 2009

Вот моя вторая попытка (после получения хороших отзывов от других) с TagSoup:

module Xml where

import Data.Char
import Text.HTML.TagSoup

type SName = String
type SValue = String

data LocalizedString = LS SName SValue
     deriving Show

getLocalizedStrings :: String -> [LocalizedString]
getLocalizedStrings = create . filterTags . parseTags
  where 
    filterTags :: [Tag] -> [Tag]
    filterTags = filter (\x -> isTagOpenName "elem" x || isTagText x)

    create :: [Tag] -> [LocalizedString]
    create (TagOpen "elem" [("name", name)] : TagText text : rest) = 
      LS name (trimWhiteSpace text) : create rest
    create (_:rest) = create rest
    create [] = []               

trimWhiteSpace :: String -> String
trimWhiteSpace = dropWhile isSpace . reverse . dropWhile isSpace . reverse

main = do
  xml <- readFile "xml.xml"  -- xml.xml contains the xml in the original question.
  putStrLn . show . getLocalizedStrings $ xml

Первая попытка продемонстрировала наивный (и ошибочный) метод для обрезки пробелов из строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...