Simplify creating Decoders for XML input.
Most code will only need the two types, the decodeXml function, and the optionalTag & multipleTag decoders.
Example:
import XML.Extra exposing ( TagSpec, Required(..)
, decodeXml, optionalTag
)
import Json.Decode as JD exposing ( Decoder )
type alias PersonRecord =
{ name : String
, age : Int
, spouse : Maybe Person
, children : List Person
}
type Person =
Person PersonRecord
personDecoder : Decoder Person
personDecoder =
JD.map4 (\name age spouse children ->
Person <| PersonRecord name age spouse children
(JD.field "name" JD.string)
(JD.field "age" JD.int)
(optionalTag "spouse"
(JD.lazy (\_ -> personDecoder))
personTagSpecs
)
(multipleTag "child"
(JD.lazy (\_ -> personDecoder))
personTagSpecs)
personTagSpecs : List TagSpec
personTagSpecs =
[ ("name", Required)
, ("age", Required)
, ("spouse", Optional)
, ("child", Multiple)
]
decodePersonXml : String -> Result String Person
decodePersonXml xml =
decodeXml xml "person" personDecoder personTagSpecs
Xml =
"""
<person>
<name>Irving</name>
<age max="100">30</age>
<sex>yes</sex>
<favoriteColor>blue</favoriteColor>
<spouse>
<name>Joan</name>
<age>28</age>
</spouse>
<child>
<name>Bob</name>
<age>1</age>
</child>
<child>
<name>Sally</name>
<age>3</age>
</child>
</person>
"""How to handle a tag in a TagSpec.
Required tags error if not there.
RequiredIgnore tags must be in the XML, but are not returned.
Optional tags will become null if not in the XML.
Multiple tags become a list.
A decoder for Optional XML tags
If the TagSpec list is empty, then the Decoder is for a simple value. Otherwise, it's for a nested tag.
A decoder for Multiple XML tags
If the TagSpec list is empty, then the Decoder is for a simple value. Otherwise, it's for a nested tag.
Decode an XML string containing a single tag into an Elm value.
The error return from decodeXml
Details about a decode error.
value is the input to the decoder.
msg is the error from Json.Decode.decodeValue with the current value appended.
Decode the contents of an XML tag with subtags.
Each TagSpec pulls one or more matching tags from the list.
Unspecified tags in the parsed Value are skipped.
You end up with a single JSON object, with the tags as keys, to which you can apply a standard JSON decoder.
Decode an XML string into a simplified Json.Encode.Value.
Convert the Xml.Value returned by Xml.Decode.decode to a Json.Encode.Value,
removing all the attributes.
A description of one tag to decode: (<tag name>, Required, <tag decoder>)