I have just started using HXT for parsing some XML documents and am wondering about how to deal with element ordering.
Unordered pairs
Consider the following two XML snippets with equivalent data.
<!-- Version 1 -->
<logistics>
<deliveryDate>2015-02-24T14:35:00Z</deliveryDate>
<deliveryAddress>Street Name 12, 93483 City, Country</deliveryAddress>
</logistics>
<!-- Version 2 -->
<logistics>
<deliveryAddress>Street Name 12, 93483 City, Country</deliveryAddress>
<deliveryDate>2015-02-24T14:35:00Z</deliveryDate>
</logistics>
In order to support both orderings of deliveryDate
and deliverAddress
I had to replace XHT's xpPair
function with my own xpUnorderedPair
function:
xpUnorderedPair :: PU a -> PU b -> PU (a,b)
xpUnorderedPair pa pb = xpAlt (const 0) ps
where ps = [ xpPair pa pb
, xpWrap (swap,undefined) $ xpPair pb pa ],
which allows me to write the following pickler function:
xpLogisticsRequirements :: PU LogisticsRequirements
xpLogisticsRequirements = xpElem "logistics" $
xpWrap (uncurry LogisticsRequirements,\r -> (deliveryDate r,deliveryAddr r)) $
xpUnorderedPair (xpElem "deliveryDate" xpickle)
(xpElem "deliveryAddress" xpText)
where LogisticsRequirements
has type UTCTime -> String -> LogisticsRequirement
.
Unordered triples
Now I can do the same with xpTriple
, creating my xpUnorderedTriple
:
xpUnorderedTriple :: PU a -> PU b -> PU c -> PU (a,b,c)
xpUnorderedTriple a' b' c' = xpAlt (const 0) ps
where ps = [ xpWrap (\(a,b,c) -> (a,b,c),undefined) $ xpTriple a' b' c'
, xpWrap (\(a,c,b) -> (a,b,c),undefined) $ xpTriple a' c' b'
, xpWrap (\(b,c,a) -> (a,b,c),undefined) $ xpTriple b' c' a'
, xpWrap (\(b,a,c) -> (a,b,c),undefined) $ xpTriple b' a' c'
, xpWrap (\(c,a,b) -> (a,b,c),undefined) $ xpTriple c' a' b'
, xpWrap (\(c,b,a) -> (a,b,c),undefined) $ xpTriple c' b' a' ]
and I can keep creating these increasingly big functions (xpUnordered5 will have 120 permutations), but this does not seem right. For the fixed numbers (i.e. pair, triple, t4, t5, etc) I guess I could use Template Haskell to create the functions, but what happens when I want to parse a list of different elements.
Unordered lists
Considering XML inputs such as this:
<myList>
<name>MyList1</name>
<elemA>...</elemA>
<elemA>...</elemA>
<elemB>...</elemB>
<elemA>...</elemA>
<elemB>...</elemB>
<elemC>...</elemC>
<elemB>...</elemB>
</myList>,
how would I go about turning them into
date MyList = MyList { name :: String
, elemsA :: [ElemA]
, elemsB :: [ElemB]
, elemsC :: [ElemC] },
considering I had the required pickle functions,
instance XmlPicker ElemA where
xpickle = xpElemA
instance XmlPicker ElemB where
xpickle = xpElemB
instance XmlPicker ElemC where
xpickle = xpElemC
I guess an option might be sorting the list of elements and then applying the sequential picklers,
xpYogurt :: PU MyList
xpYogurt = xpElem "myList" $
xpWrap (uncurry4 MyList,\l -> (name l
,elemsA l
,elemsB l
,elemsC l)) $
xp4Tuple (xpElem "name" xpPrim)
(xpList xpElemA)
(xpList xpElemB)
(xpList xpElemC)
but that does not seem very elegant and requires additional sorting logic!
Thanks for any help!
No comments:
Post a Comment