22 val s = new StringBuilder |
22 val s = new StringBuilder |
23 append_tree(this, s) |
23 append_tree(this, s) |
24 s.toString |
24 s.toString |
25 } |
25 } |
26 } |
26 } |
27 case class Elem(name: String, attributes: Attributes, body: List[Tree]) extends Tree |
27 case class Elem(markup: Markup, body: List[Tree]) extends Tree |
28 case class Text(content: String) extends Tree |
28 case class Text(content: String) extends Tree |
29 |
29 |
30 def elem(name: String, body: List[Tree]) = Elem(name, Nil, body) |
30 def elem(name: String, body: List[Tree]) = Elem(Markup(name, Nil), body) |
31 def elem(name: String) = Elem(name, Nil, Nil) |
31 def elem(name: String) = Elem(Markup(name, Nil), Nil) |
32 |
32 |
33 |
33 |
34 /* string representation */ |
34 /* string representation */ |
35 |
35 |
36 private def append_text(text: String, s: StringBuilder) { |
36 private def append_text(text: String, s: StringBuilder) { |
54 } |
54 } |
55 } |
55 } |
56 |
56 |
57 private def append_tree(tree: Tree, s: StringBuilder) { |
57 private def append_tree(tree: Tree, s: StringBuilder) { |
58 tree match { |
58 tree match { |
59 case Elem(name, atts, Nil) => |
59 case Elem(Markup(name, atts), Nil) => |
60 s ++= "<"; append_elem(name, atts, s); s ++= "/>" |
60 s ++= "<"; append_elem(name, atts, s); s ++= "/>" |
61 case Elem(name, atts, ts) => |
61 case Elem(Markup(name, atts), ts) => |
62 s ++= "<"; append_elem(name, atts, s); s ++= ">" |
62 s ++= "<"; append_elem(name, atts, s); s ++= ">" |
63 for (t <- ts) append_tree(t, s) |
63 for (t <- ts) append_tree(t, s) |
64 s ++= "</"; s ++= name; s ++= ">" |
64 s ++= "</"; s ++= name; s ++= ">" |
65 case Text(text) => append_text(text, s) |
65 case Text(text) => append_text(text, s) |
66 } |
66 } |
70 /* iterate over content */ |
70 /* iterate over content */ |
71 |
71 |
72 private type State = Option[(String, List[Tree])] |
72 private type State = Option[(String, List[Tree])] |
73 |
73 |
74 private def get_next(tree: Tree): State = tree match { |
74 private def get_next(tree: Tree): State = tree match { |
75 case Elem(_, _, body) => get_nexts(body) |
75 case Elem(_, body) => get_nexts(body) |
76 case Text(content) => Some(content, Nil) |
76 case Text(content) => Some(content, Nil) |
77 } |
77 } |
78 private def get_nexts(trees: List[Tree]): State = trees match { |
78 private def get_nexts(trees: List[Tree]): State = trees match { |
79 case Nil => None |
79 case Nil => None |
80 case t :: ts => get_next(t) match { |
80 case t :: ts => get_next(t) match { |
125 else |
125 else |
126 lookup(x) match { |
126 lookup(x) match { |
127 case Some(y) => y |
127 case Some(y) => y |
128 case None => store(x.map(p => (cache_string(p._1), cache_string(p._2)))) |
128 case None => store(x.map(p => (cache_string(p._1), cache_string(p._2)))) |
129 } |
129 } |
|
130 def cache_markup(x: Markup): Markup = |
|
131 lookup(x) match { |
|
132 case Some(y) => y |
|
133 case None => |
|
134 x match { |
|
135 case Markup(name, props) => |
|
136 store(Markup(cache_string(name), cache_props(props))) |
|
137 } |
|
138 } |
130 def cache_tree(x: XML.Tree): XML.Tree = |
139 def cache_tree(x: XML.Tree): XML.Tree = |
131 lookup(x) match { |
140 lookup(x) match { |
132 case Some(y) => y |
141 case Some(y) => y |
133 case None => |
142 case None => |
134 x match { |
143 x match { |
135 case XML.Elem(name, props, body) => |
144 case XML.Elem(markup, body) => |
136 store(XML.Elem(cache_string(name), cache_props(props), cache_trees(body))) |
145 store(XML.Elem(cache_markup(markup), cache_trees(body))) |
137 case XML.Text(text) => XML.Text(cache_string(text)) |
146 case XML.Text(text) => store(XML.Text(cache_string(text))) |
138 } |
147 } |
139 } |
148 } |
140 def cache_trees(x: List[XML.Tree]): List[XML.Tree] = |
149 def cache_trees(x: List[XML.Tree]): List[XML.Tree] = |
141 if (x.isEmpty) x |
150 if (x.isEmpty) x |
142 else |
151 else |
156 } |
165 } |
157 |
166 |
158 def document_node(doc: org.w3c.dom.Document, tree: Tree): org.w3c.dom.Node = |
167 def document_node(doc: org.w3c.dom.Document, tree: Tree): org.w3c.dom.Node = |
159 { |
168 { |
160 def DOM(tr: Tree): org.w3c.dom.Node = tr match { |
169 def DOM(tr: Tree): org.w3c.dom.Node = tr match { |
161 case Elem(Markup.DATA, Nil, List(data, t)) => |
170 case Elem(Markup(Markup.DATA, Nil), List(data, t)) => |
162 val node = DOM(t) |
171 val node = DOM(t) |
163 node.setUserData(Markup.DATA, data, null) |
172 node.setUserData(Markup.DATA, data, null) |
164 node |
173 node |
165 case Elem(name, atts, ts) => |
174 case Elem(Markup(name, atts), ts) => |
166 if (name == Markup.DATA) |
175 if (name == Markup.DATA) |
167 error("Malformed data element: " + tr.toString) |
176 error("Malformed data element: " + tr.toString) |
168 val node = doc.createElement(name) |
177 val node = doc.createElement(name) |
169 for ((name, value) <- atts) node.setAttribute(name, value) |
178 for ((name, value) <- atts) node.setAttribute(name, value) |
170 for (t <- ts) node.appendChild(DOM(t)) |
179 for (t <- ts) node.appendChild(DOM(t)) |