Created
April 15, 2014 23:34
-
-
Save benkolera/10789041 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scalaz._ | |
import syntax.std.option._ | |
import syntax.monad._ | |
import syntax.show._ | |
import xml._ | |
import cursor._ | |
import Xml._ | |
object DecoderTest { | |
// | |
// -- Some types + decoders for attrs and grabbing text from elements -------- | |
case class DecodeError( | |
cursorHistory: History , | |
decodeDesc: String , | |
err: String | |
) | |
type DecodeResult[+A] = DecodeError \/ A | |
type DecoderT[M[+_],+A] = Kleisli[M,Content,A] | |
type Decoder[+A] = DecoderT[DecodeResult,A] | |
def decoder[A]( run:Content => DecodeResult[A] ):Decoder[A] = { | |
Kleisli[DecodeResult,Content,A]( run ) | |
} | |
def shiftedContent( | |
s:Shift , desc:String | |
)( | |
c:Content | |
): DecodeResult[(History,Content)] = { | |
val hc = s.run( c ) | |
hc.cursor.map( hc.history -> ~_ ).toRightDisjunction( | |
DecodeError( hc.history , desc, "Failed cursor" ) | |
) | |
} | |
def attributeDecoder( attrName:String )( s:Shift ) = decoder[String] { c => | |
val desc = s"Find attr $attrName" | |
shiftedContent( s , desc )(c).flatMap{ case (h,c) => | |
c.elem.flatMap( | |
_.attribs.find( _.key.name == attrName.toList ) | |
).fold[DecodeResult[String]]( | |
-\/(DecodeError(h,desc,"Couldn't find attribute")) | |
)( attr => | |
\/-(attr.value.mkString) | |
) | |
} | |
} | |
def textDecoder( s:Shift ) = decoder[String] { c => | |
val desc = s"Find text element" | |
shiftedContent( s , desc )(c).flatMap{ case (h,c) => | |
c.elem.fold[DecodeResult[String]]( | |
-\/(DecodeError(h,desc,"Cursor was not at an element")) | |
)( e => | |
\/-(e.strContent.mkString) | |
) | |
} | |
} | |
// -- Some helper predicates ------------------------------------------------- | |
def nameCPred( name:String ) = Predicate.predicate[Cursor]( | |
c => c.current.elem.map( _.name.name == name.toList ).getOrElse(false) , | |
Some( s"Element named: $name".toList ) | |
) | |
val findRecName: String => Shift = nameCPred _ andThen findRec | |
val findChildName: String => Shift = nameCPred _ andThen findChild | |
// -- And now lets run it ---------------------------------------------------- | |
val xmlStr = """<envelope> | |
<header> | |
<headerstuff>Stuff<headerstuff> | |
</header> | |
<body> | |
<field1><nestedfield>foo</nestedfield></field1> | |
<field2 attra="attribute a">bar</field2> | |
</body> | |
</envelope>""" | |
def main( args:Array[String] ):Unit = { | |
val p = xmlStr.parseXml | |
val attra = attributeDecoder( "attra" )( findRecName( "field2" ) ) | |
var nField = textDecoder( | |
findRecName("field1") >=> findChildName("nestedfield") | |
) | |
val r = ( attra |@| nField ){ (a,b) => s"Attrib($a) Field:($b)" }.run( p.head ) | |
println( r ) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment