Извлечение нескольких элементов в контексте процесса Arrow - PullRequest
5 голосов
/ 02 октября 2019

Я хочу проанализировать следующий пример XML-файла без модуля выбора.

<?xml version="1.0" encoding="utf-8" ?>
<Groups> 
    <Name>ABC</Name>
    <GroupA>
        <Name>Foo</Name>
        <Sum>100</Sum>
    </GroupA>
    <GroupB>
        <Name>Bar</Name>
        <Sum>0</Sum>
    </GroupB>
</Groups>

Я получил следующее:

{-# language Arrows #-}

import Text.XML.HXT.Core

data Groups = Groups GroupA GroupB deriving Show
data GroupA = GroupA String String deriving Show
data GroupB = GroupB String String deriving Show


readGroup :: LA XmlTree Groups
readGroup = deep (isElem >>> hasName "Groups") >>> getChildren >>>
  proc root -> do
    a <- readGroupA -< root
    b <- readGroupB -< root
    returnA -< Groups a b

readGroupA :: LA XmlTree GroupA
readGroupA = isElem >>> hasName "GroupA" >>> getChildren >>>
  proc root -> do
    n <- isElem >>> hasName "Name" /> getText -< root
    s <- isElem >>> hasName "Sum"  /> getText -< root
    returnA -< GroupA n s

readGroupB :: LA XmlTree GroupB
readGroupB = isElem >>> hasName "GroupB" >>> getChildren >>>
  proc root -> do
    n <- isElem >>> hasName "Name" /> getText -< root
    s <- isElem >>> hasName "Sum"  /> getText -< root
    returnA -< GroupB n s

К сожалению, это не работает. Если я пытаюсь извлечь только один элемент в proc контексте, это работает. Но попытка извлечь несколько элементов всегда приведет к ошибке \ возврату пустого списка. У меня может быть неправильное понимание композиции >>>.

Я запускаю пример с runLa (xreadDoc >>> readGroups)

1 Ответ

0 голосов
/ 07 октября 2019

Попробуйте это:

readGroup :: LA XmlTree Groups
readGroup = deep (isElem >>> hasName "Groups") >>>
  proc root -> do
    a <- getChildren >>> readGroupA -< root
    b <- getChildren >>> readGroupB -< root
    returnA -< Groups a b

readGroupA :: LA XmlTree GroupA
readGroupA = isElem >>> hasName "GroupA" >>>
  proc root -> do
    n <- getChildren >>> isElem >>> hasName "Name" /> getText -< root
    s <- getChildren >>> isElem >>> hasName "Sum"  /> getText -< root
    returnA -< GroupA n s

readGroupB :: LA XmlTree GroupB
readGroupB = isElem >>> hasName "GroupB" >>>
  proc root -> do
    n <- getChildren >>> isElem >>> hasName "Name" /> getText -< root
    s <- getChildren >>> isElem >>> hasName "Sum"  /> getText -< root
    returnA -< GroupB n s

Когда вызов getChildren находится за пределами do -блока, вы делаете коммит одному ребенку, даже не введя proc. Внутри proc вы проверяете (например), имеет ли этот ребенок имя Name и имя Sum. Неудивительно, что вы не найдете ни одного ребенка, отвечающего этим противоречивым требованиям.

Перемещая getChildren внутрь, вы позволяете проходить различным дочерним элементам (например) n и s.

...