14 { |
14 { |
15 /* datatype representation */ |
15 /* datatype representation */ |
16 |
16 |
17 type Attributes = List[(String, String)] |
17 type Attributes = List[(String, String)] |
18 |
18 |
19 abstract class Tree |
19 abstract class Tree { |
20 case class Elem(name: String, attributes: Attributes, body: List[Tree]) extends Tree { |
20 override def toString = { |
21 override def toString = append_tree(this, new StringBuilder).toString |
21 val s = new StringBuilder |
|
22 append_tree(this, s) |
|
23 s.toString |
|
24 } |
22 } |
25 } |
23 case class Text(content: String) extends Tree { |
26 case class Elem(name: String, attributes: Attributes, body: List[Tree]) extends Tree |
24 override def toString = append_tree(this, new StringBuilder).toString |
27 case class Text(content: String) extends Tree |
25 } |
|
26 |
28 |
27 |
29 |
28 /* string representation */ |
30 /* string representation */ |
29 |
31 |
30 private def append_text(text: String, s: StringBuilder) { |
32 private def append_text(text: String, s: StringBuilder) { |
32 case '<' => s.append("<") |
34 case '<' => s.append("<") |
33 case '>' => s.append(">") |
35 case '>' => s.append(">") |
34 case '&' => s.append("&") |
36 case '&' => s.append("&") |
35 case '"' => s.append(""") |
37 case '"' => s.append(""") |
36 case '\'' => s.append("'") |
38 case '\'' => s.append("'") |
37 case _ => s.append(c) |
39 case _ => s.append(c) |
38 } |
40 } |
39 } |
41 } |
40 |
42 |
41 private def append_elem(name: String, atts: Attributes, s: StringBuilder) { |
43 private def append_elem(name: String, atts: Attributes, s: StringBuilder) { |
42 s.append(name) |
44 s.append(name) |
43 for ((a, x) <- atts) { |
45 for ((a, x) <- atts) { |
44 s.append(" "); s.append(a); s.append("=\""); append_text(x, s); s.append("\"") |
46 s.append(" "); s.append(a); s.append("=\""); append_text(x, s); s.append("\"") |
45 } |
47 } |
46 } |
48 } |
47 |
49 |
48 private def append_tree(tree: Tree, s: StringBuilder): StringBuilder = { |
50 private def append_tree(tree: Tree, s: StringBuilder) { |
49 tree match { |
51 tree match { |
50 case Elem(name, atts, Nil) => |
52 case Elem(name, atts, Nil) => |
51 s.append("<"); append_elem(name, atts, s); s.append("/>") |
53 s.append("<"); append_elem(name, atts, s); s.append("/>") |
52 case Elem(name, atts, ts) => |
54 case Elem(name, atts, ts) => |
53 s.append("<"); append_elem(name, atts, s); s.append(">") |
55 s.append("<"); append_elem(name, atts, s); s.append(">") |
54 for (t <- ts) append_tree(t, s) |
56 for (t <- ts) append_tree(t, s) |
55 s.append("</"); s.append(name); s.append(">") |
57 s.append("</"); s.append(name); s.append(">") |
56 case Text(text) => append_text(text, s) |
58 case Text(text) => append_text(text, s) |
57 } |
59 } |
58 s |
|
59 } |
60 } |
60 |
61 |
61 |
62 |
62 /* iterate over content */ |
63 /* iterate over content */ |
63 |
64 |