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>
"""
( String, Required )
A description of one tag to decode: (
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.
requiredTag : String -> Json.Decode.Decoder value -> List TagSpec -> Json.Decode.Decoder value
A decoder for Required
XML tags
If the TagSpec
list is empty, then the Decoder
is for a simple value. Otherwise, it's for a nested tag.
optionalTag : String -> Json.Decode.Decoder value -> List TagSpec -> Json.Decode.Decoder (Maybe value)
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.
multipleTag : String -> Json.Decode.Decoder value -> List TagSpec -> Json.Decode.Decoder (List value)
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.
decodeXml : String -> String -> Json.Decode.Decoder value -> List TagSpec -> Result Error value
Decode an XML string containing a single tag into an Elm value.
The error return from decodeXml
{ value : Json.Decode.Value
, msg : String
}
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.
tagDecoder : Json.Decode.Decoder value -> List TagSpec -> Json.Decode.Decoder value
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.
stringToJson : String -> Result String Json.Encode.Value
Decode an XML string into a simplified Json.Encode.Value
.
xmlToJson2 : Xml.Value -> Json.Encode.Value
Convert the Xml.Value
returned by Xml.Decode.decode
to a Json.Encode.Value
,
removing all the attributes.