Created
March 20, 2011 19:34
-
-
Save kxbmap/878592 to your computer and use it in GitHub Desktop.
case class + パターンマッチングで再帰的なXMLを生成する
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
package com.example.kvxml | |
import _root_.scala.xml.{Elem, MetaData, Node, NodeSeq, Null, Text, TopScope, UnprefixedAttribute} | |
sealed abstract class Value | |
case class StringValue(str: String) extends Value | |
case class ValueSeq(seq: Seq[Value]) extends Value | |
case class KeyValue(key: String, attributes: Map[String, String], value: Value) extends Value { | |
def this(key: String, value: Value) = this(key, Map.empty, value) | |
} | |
object KeyValueXML { | |
def toXML(kv: KeyValue): Node = { | |
def xml(k: String, a: Map[String, String], v: NodeSeq): Node = { | |
val meta = ((Null: MetaData) /: a){ (meta, attr) => | |
new UnprefixedAttribute(attr._1, attr._2, meta) | |
} | |
Elem(null, k, meta, TopScope, v: _*) | |
} | |
def nodes(v: Value): NodeSeq = v match { | |
case StringValue(s) => Text(s) | |
case ValueSeq(s) => s flatMap nodes | |
case KeyValue(k, a, v) => xml(k, a, nodes(v)) | |
} | |
xml(kv.key, kv.attributes, nodes(kv.value)) | |
} | |
} |
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
package com.example.kvxml | |
import org.specs2._ | |
import scala.xml.PrettyPrinter | |
class KeyValueSpec extends Specification { def is = | |
"case class + パターンマッチング版KeyValueのテスト" ^ | |
"XMLリテラルと一致する" ! S.example1 ^ | |
"PrettyPrinterで生成したStringが一致する" ! S.example2 ^ | |
"改行とインデント込みでXMLリテラルに一致する" ! S.example3 ^ | |
end | |
object S { | |
implicit def string2value(str: String): Value = StringValue(str) | |
implicit def seq2value(seq: Seq[Value]): Value = ValueSeq(seq) | |
val kv = | |
KeyValue("langs", Map("type" -> "current"), Seq( | |
new KeyValue("key1", "value1"), | |
new KeyValue("key2", "value2"), | |
new KeyValue("key3", Seq( | |
new KeyValue("key3-1", "value3-1"), | |
new KeyValue("key3-2", "value3-2") | |
)) | |
)) | |
def example1 = KeyValueXML.toXML(kv) must_== | |
<langs type="current"><key1>value1</key1><key2>value2</key2><key3><key3-1>value3-1</key3-1><key3-2>value3-2</key3-2></key3></langs> | |
def example2 = { | |
val expect = """<langs type="current"> | |
| <key1>value1</key1> | |
| <key2>value2</key2> | |
| <key3> | |
| <key3-1>value3-1</key3-1> | |
| <key3-2>value3-2</key3-2> | |
| </key3> | |
|</langs>""".stripMargin | |
new PrettyPrinter(80, 2).format(KeyValueXML.toXML(kv)) must_== expect | |
} | |
val kv2 = { | |
val nl = "\n" | |
val indent = " " | |
KeyValue("langs", Map("type" -> "current"), Seq[Value]( | |
nl + indent, | |
new KeyValue("key1", "value1"), | |
nl + indent, | |
new KeyValue("key2", "value2"), | |
nl + indent, | |
new KeyValue("key3", Seq[Value]( | |
nl + indent * 2, | |
new KeyValue("key3-1", "value3-1"), | |
nl + indent * 2, | |
new KeyValue("key3-2", "value3-2"), | |
nl + indent | |
)), | |
nl | |
)) | |
} | |
def example3 = KeyValueXML.toXML(kv2) must_== | |
<langs type="current"> | |
<key1>value1</key1> | |
<key2>value2</key2> | |
<key3> | |
<key3-1>value3-1</key3-1> | |
<key3-2>value3-2</key3-2> | |
</key3> | |
</langs> | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment