Neil
Neil

Reputation: 359

Hxt and parsing optional elements

I'm pulling my hair out trying to parse an optional element using HXT in the following xml snippet:

<ns9:accountBankingInfo>
  <key>
    <accountId>10</accountId>
    <bankingId>01</bankingId>
  </key>
  <bankingInfo>
    <description>Bigbank Co.</description>
    <eft>
        <bankCode>222</bankCode>
        <transit>111</transit>
        <accountNumber>3333333</accountNumber>
    </eft>
   </bankingInfo>
   <defaultType>ACCOUNT</defaultType> <!-- optional -->
</ns9:accountBankingInfo>

I'm using a Maybe to represent the defaultType element:

data BankingInfo = BankingInfo { bankingID   :: String
                               , bankingDesc :: String
                               , bankCode    :: String  
                               , bankTransit :: String  
                               , bankAccount :: String
                               , defaultType :: Maybe String  
                               } deriving (Show, Eq)

I'm parsing the accountBankingInfo element like so:

bankParser :: ArrowXml a => a XmlTree BankingInfo
bankParser = deep (isElem >>> hasLocalPart "accountBankingInfo") >>> proc x -> do
                   i <- getText <<< getChildren <<< deep (hasName "bankingId") -< x
                   d <- getText <<< getChildren <<< deep (hasName "description") -< x
                   b <- getText <<< getChildren <<< deep (hasName "bankCode") -< x
                   t <- getText <<< getChildren <<< deep (hasName "transit") -< x
                   a <- getText <<< getChildren <<< deep (hasName "accountNumber") -< x
                   g <- nc "defaultType" -< x

                   returnA -< BankingInfo i d b t a g

nc name = ifA (deep (hasName name)) (getChildren >>> getText >>> arr Just) (arr (const Nothing))

It compiles, but when I parse a file, I don't get any BankingInfo's returned. If I change the BankingInfo type to remove the defaultType and don't worry about parsing for that element, it all works successfully.

Is there a simple way to handle optional elements in the XML and convert that to Maybe x?

Upvotes: 1

Views: 96

Answers (1)

Neil
Neil

Reputation: 359

I just discovered the withDefault function and was able to get it working like so:

bankParser :: ArrowXml a => a XmlTree BankingInfo
bankParser = deep (isElem >>> hasLocalPart "accountBankingInfo") >>> proc x -> do
                   i <- getText <<< getChildren <<< deep (hasName "bankingId") -< x
                   d <- getText <<< getChildren <<< deep (hasName "description") -< x
                   b <- getText <<< getChildren <<< deep (hasName "bankCode") -< x
                   t <- getText <<< getChildren <<< deep (hasName "transit") -< x
                   a <- getText <<< getChildren <<< deep (hasName "accountNumber") -< x
                   g <- withDefault (arr Just <<< getText <<< getChildren <<< deep (hasName "defaultType")) Nothing -< x
                   returnA -< BankingInfo i d b t a g

Upvotes: 1

Related Questions