parseCandidatesFromXML xmlString = do
        parseResult <- mkParseResult xmlString
        let contentRoot = mkContentRoot parseResult
        mapM parseDetectedSurfaceForm $ detectedSurfaceForms contentRoot
    where
        detectedSurfaceForms = keep /> tag "surfaceForm"
        parseDetectedSurfaceForm content = do
            cSurfaceForm <- parseSurfaceForm content
            cOffset <- fmap read $ parseOffset content
            cEntities <- mapM parseEntities $ (keep /> tag "resource") content
            return $ SpotlightCandidates cSurfaceForm cOffset cEntities
        parseEntities content = do
            eURI <- candidateAttr "uri"
            eSupport <- fmap read $ candidateAttr "support"
            eLabel <- candidateAttr "label"
            eContextualScore <- fmap read $ candidateAttr "contextualScore"
            ePercentSecondRank <- fmap read $ 
                candidateAttr "percentageOfSecondRank"
            ePriorScore <- fmap read $ candidateAttr "priorScore"
            eFinalScore <- fmap read $ candidateAttr "finalScore"
            return $ CandidateEntity eLabel eURI eContextualScore
                ePercentSecondRank eSupport ePriorScore eFinalScore
            where
                candidateAttr attr = lookup' (N attr) candidateAttrs
                candidateAttrs = map stringsForAttValues $ attrs $
                    contentElem content
        parseSurfaceForm = lookup' (N "name") . sfAttrs
        parseOffset = lookup' (N "offset") . sfAttrs
        sfAttrs = map stringsForAttValues . attrs . contentElem
parseCandidatesFromXML xmlString = do
        parseResult <- mkParseResult xmlString
        let contentRoot = mkContentRoot parseResult
        mapM parseDetectedSurfaceForm $ detectedSurfaceForms contentRoot
    where
        detectedSurfaceForms = keep /> tag "surfaceForm"
        parseDetectedSurfaceForm content = do
            cSurfaceForm <- parseSurfaceForm content
            cOffset <- fmap read $ parseOffset content
            cEntities <- mapM parseEntities $ (keep /> tag "resource") content
            return $ SpotlightCandidates cSurfaceForm cOffset cEntities
        parseEntities content = do
            eURI <- candidateAttr "uri"
            eSupport <- fmap read $ candidateAttr "support"
            eLabel <- candidateAttr "label"
            eContextualScore <- fmap read $ candidateAttr "contextualScore"
            ePercentSecondRank <- fmap read $ 
                candidateAttr "percentageOfSecondRank"
            ePriorScore <- fmap read $ candidateAttr "priorScore"
            eFinalScore <- fmap read $ candidateAttr "finalScore"
            return $ CandidateEntity eLabel eURI eContextualScore
                ePercentSecondRank eSupport ePriorScore eFinalScore
            where
                candidateAttr attr = lookup' (N attr) candidateAttrs
                candidateAttrs = map stringsForAttValues $ attrs $
                    contentElem content
        parseSurfaceForm = lookup' (N "name") . sfAttrs
        parseOffset = lookup' (N "offset") . sfAttrs
        sfAttrs = map stringsForAttValues . attrs . contentElem
parseCandidatesFromXML xmlString = do
        parseResult <- mkParseResult xmlString
        let contentRoot = mkContentRoot parseResult
        mapM parseDetectedSurfaceForm $ detectedSurfaceForms contentRoot
    where
        detectedSurfaceForms = keep /> tag "surfaceForm"
        parseDetectedSurfaceForm content = do
            cSurfaceForm <- parseSurfaceForm content
            cOffset <- fmap read $ parseOffset content
            cEntities <- mapM parseEntities $ (keep /> tag "resource") content
            return $ SpotlightCandidates cSurfaceForm cOffset cEntities
        parseEntities content = do
            eURI <- candidateAttr "uri"
            eSupport <- fmap read $ candidateAttr "support"
            eLabel <- candidateAttr "label"
            eContextualScore <- fmap read $ candidateAttr "contextualScore"
            ePercentSecondRank <- fmap read $ 
                candidateAttr "percentageOfSecondRank"
            ePriorScore <- fmap read $ candidateAttr "priorScore"
            eFinalScore <- fmap read $ candidateAttr "finalScore"
            return $ CandidateEntity eLabel eURI eContextualScore
                ePercentSecondRank eSupport ePriorScore eFinalScore
            where
                candidateAttr attr = lookup' (N attr) candidateAttrs
                candidateAttrs = map stringsForAttValues $ attrs $
                    contentElem content
        parseSurfaceForm = lookup' (N "name") . sfAttrs
        parseOffset = lookup' (N "offset") . sfAttrs
        sfAttrs = map stringsForAttValues . attrs . contentElem