
Dear Group, I have just spent many hours staring at code and losing some hair. My hope is to save you the same experience someday. Here was my goal: Take some XML, like <photo url="somewhere" align="left" alt=""/> and replace the align attribute with a class attribute, but only if the value of the align attribute was not null. This led to to followed (hugely condensed) attempts: ------------------------------------------------------------------------
{-# LANGUAGE Arrows #-} import Text.XML.HXT.Core
-- <photo url="somewhere" align="left" alt=""/> testString = "
" toClass :: b -> QName toClass = const (mkName "class") try f = runLA (xread >>> processTopDown f) testString
test1 = try $ hasAttrValue "align" (not.null) >>> processAttrl (changeAttrName toClass `when` hasName "align" ) test2 = try $ processAttrl (changeAttrName toClass `when` hasAttrValue "align" (not.null)) test3 = try $ processAttrl (changeAttrName toClass `when` hasName "align") `when` hasAttrValue "align" (not.null)
run = do print test1 print test2 print test3
result of run: [NTree (XTag "photo" [NTree (XAttr "url") [NTree (XText "somewhere") []],NTree (XAttr "class") [NTree (XText "left") []],NTree (XAttr "alt") []]) []] [NTree (XTag "photo" [NTree (XAttr "url") [NTree (XText "somewhere") []],NTree (XAttr "align") [NTree (XText "left") []],NTree (XAttr "alt") []]) []] [NTree (XTag "photo" [NTree (XAttr "url") [NTree (XText "somewhere") []],NTree (XAttr "class") [NTree (XText "left") []],NTree (XAttr "alt") []]) []] test1 and test3 performed as desired, needless to say I started out with something similar to test2 and was almost crying because the align attribute didn't change. Why? In test1, I run through the tree and select the elements which have a non-null align attribute. (hasAttrValue "align" (not.null)) Then for each of these elements I process their attributes. (processAttrl) where I change the attribute name to "class" (changeAttrName toClass) WHEN the attribute name is "align" (`when` hasName "align") Result: Joy In test2, I run through the tree and process every attribute list (processAttrl) I change the name of the attribute to "class" (changeAttrName toClass) WHEN the align attribute is not null (`when` hasAttrValue "align" (not.null))) Result: Nothing changes, - No Joy In test3, I run through the tree process every attribute list (processAttrl) WHEN the align attribute is not null (`when` hasAttrValue "align" (not.null)) and in that case I change the attribute name to "class" (changeAttrName toClass) WHEN the attribute is named "align" (`when` hasName "align") Result: Joy After staring at test2 for more time that I would like to acknowledge, I (think) I realized the following. In test2 I thought the (hasAttrValue "align" (not.null)) was referring to the tree that was coming into the test, but actually it is referring to the list of attributes that is generated by processAttrl. This list of attributes does not itself have any attributes, thus the (hasAttrValue "align" (not.null)) code never succeeds, and thus the (changeAttrName toClass) is never executed. Lessons learned: I'm not really sure, but it is these kind of subtleties that make me sometimes long for my old friend Perl. Best wishes, Henry Laxen -- Nadine & Henry Laxen Belle, Venus, Aphrodite 10580 N. McCarran Blvd. Adonis, Miss Parker & Jarod Suite 115-396 Via Alta # 6 Reno, Nevada Chapala, Jalisco, Mexico 89503-1896 CP 45900 The rest is silence. (Hamlet)