Take the 2-minute tour ×

I'm continuing the problem from this question. The task is to search through the mb nodes for the model attribute with a certain value, then filter out the ones that did not match the value attribute in the dmiattr element. Once filtered, I need to capture a list of values from the rev attribute. I've made some progress. I am able to match against the model attribute and capture the values of the rev attribute.

But I am having difficulty drilling down to the child dmiattr. I think I have almost all the correct functions, perhaps not the correct combinators. And maybe the logic of my code is wonky too. I'm not sure where it goes wrong. Feedback approciated.

import Text.XML
import Text.XML.Cursor
import qualified Data.Text as T

getProfiles :: AdviseConf -> IO () -- AdviseResult
getProfiles  (AdviseConf model mb) = do
   doc <- Text.XML.readFile def xmlFile
   let cursor = fromDocument doc
   _ <- Prelude.writeFile "test.txt" $
        show                         $
        cursor                       $//
        check findNode               &.// -- &//
        attributeIs "model" "460"    &.//
        check findMB                 &.//
        followingSibling             &.//
        attributeIs "value" "GF615M-P33  (MS-7597)" &.//
        attribute "rev"
   return ()

findNode :: Cursor -> Bool
findNode c = case (attribute "rev" c) of
              []  -> False
              otherwise -> True

findMB :: Cursor -> Bool
findMB c = case ( attribute "value"  c) of
            [] -> False
            otherwise -> True
share|improve this question

1 Answer 1

up vote 1 down vote accepted

I didn't follow all the details in your code (what's the purpose of followingSibling, for example?). But I think this gets you pretty close to what you were looking for:

{-# LANGUAGE OverloadedStrings #-}
import Text.XML
import Text.XML.Cursor

main = do
   doc <- Text.XML.readFile def "test.xml"
   let cursor = fromDocument doc
   print $
        cursor                       $//
        hasAttribute "rev"           >=>
        attributeIs "model" "460"    &.//
        check (\c -> c $// element "dmiattr"
                       >=> attributeIs "value" "GF615M-P33  (MS-7597)") >=>
        attribute "rev"

Notice that the argument to the check function returns a list. If that list is empty, it's treated the same as False, and therefore the check fails.

share|improve this answer
My reasoning comes from not really understanding what some of these functions do. I thought that since the <dmiattr element I was looking for was the second child, I had to use followingSibling to get to it. I'll try out your code, and I imagine if it's not exactly what I need I can play around with it. Thanks again. –  Michael Litchard Nov 9 '12 at 18:26

Your Answer


