You need to decide what you want when the SubClass node doesn't exist. As I see it, you have two choices:
A missing SubClass node means that
subClass
is the empty string. In that case, simply change your parser to fall back to the empty string when the arrow built aroundatTag "rdfs:subClassOf"
fails:getClass = atTag "owl:Class" >>> proc l -> do className <- parseClass -< l subClass <- getSubClass -< l returnA -< Class { name = split className, subClassOf = split subClass } where getSubClass = (atTag "rdfs:subClassOf" >>> parseSubClass) `orElse` arr (const "")
A missing SubClass node means that
subClass
isNothing
. This requires changing your data definition so thatsubClassOf
is of typeMaybe String
, but after that it's fairly similar to the previous answer:getClass = atTag "owl:Class" >>> proc l -> do className <- parseClass -< l subClass <- getSubClass -< l returnA -< Class { name = split className, subClassOf = fmap split subClass } where getSubClass = (atTag "rdfs:subClassOf" >>> parseSubClass >>> arr Just) `orElse` arr (const Nothing)
Just so we're clear, because you say that this isn't working in the comments, here's exactly the full program I'm running, which works fine for me:
{-# LANGUAGE Arrows #-}
import System.Environment --para uso do getArgs
import Data.List.Split (splitOn)
import Text.XML.HXT.Core
data Class = Class {
name ::String,
subClassOf ::String
} deriving (Show,Eq)
main = do
[src]<- getArgs
parser <- runX(readDocument [ withValidate no] src >>> getClass)
print parser
parseClass = ifA (hasAttr "rdf:about")
(getAttrValue "rdf:about")
(getAttrValue "rdf:ID")
parseSubClass = getAttrValue "rdf:resource"
split l = if(length (splitOn "#" l) >1) then (splitOn "#" l !! 1) else l
atTag tag = deep (isElem >>> hasName tag)
getClass = atTag "owl:Class" >>>
proc l -> do
className <- parseClass -< l
subClass <- getSubClass -< l
returnA -< Class { name = split className, subClassOf = split subClass }
where
getSubClass =
(atTag "rdfs:subClassOf" >>> parseSubClass)
`orElse` arr (const "")
Note that if you really don't want to combine multple arrow steps with >>>
or <<<
, another possibility is to use an inner proc
:
getClass = atTag "owl:Class" >>>
proc l -> do
className <- parseClass -< l
subClass <- (proc l' -> do
s <- atTag "rdfs:subClassOf" -< l'
parseSubClass -< s)
`orElse` constA "" -< l
returnA -< Class { name = split className, subClassOf = split subClass}