haskellhxt

Using HXT to modify XML


I'm trying to modify an XML file of the form:

<plist version="1.0">
<dict>
    <key>items</key>
    <array>
        <dict>
            <key>assets</key>
            <array>
                <dict>
                    <key>kind</key>
                    <string>software-package</string>
                    <key>url</key>
                    <string>https://s3.xyz.amazonaws.com/xyz/xyz.ipa</string>
                </dict>
                <dict>
                    <key>kind</key>
                    <string>display-image</string>
                    <key>url</key>
                    <string>https://s3.xyz.amazonaws.com/xyz/xyz.57x57.png</string>
                </dict>
            </array>
        </dict>
    </array>
</dict>

I want to modify the contents of the node <string>https://s3.xyz.amazonaws.com/xyz/xyz.ipa</string>

I can find the related sibling node with the following

import Text.XML.HXT.Core

main = do
  plistString <- readFile "manifest.plist"
  let plistDoc = readString [withValidate no, withSubstDTDEntities no] plistString
  node <- runX  $ plistDoc >>> deep (hasText ( == "software-package")) 
  print node

but I don't seem to be able to select the associated sibling nodes (tried followingSiblingAxis and moveUp >>> getChildren) which would then allow me to manipulate the required node. Is it a problem to do with the difference between NavigatableTree and NTree; the node I'm shows as NTree (XText "software-package") []]

It would really help me if any answers assume a very limited exposure to arrows.

Thanks.


Solution

  • I've solved the problem in a different way. It doesn't feel as robust (matching a substring for xyz.ipa), but it unblocked me while I await inspiration:

    import Text.XML.HXT.Core
    import Data.Char (toUpper)
    
    uppercase = map toUpper
    
    main = do
      plistString <- readFile "manifest.plist"
      let plistDoc = readString [withValidate no, withSubstDTDEntities no] plistString
      node <- runX . xshow $ plistDoc >>> processTopDown (ifA (hasText ( isInfixOf "xyz.ipa")) (changeText uppercase) (this))
      print node