Skip to content

Commit e8a7d50

Browse files
buraqadriaanm
buraq
authored andcommitted
traversing of xml nodes
1 parent a38f055 commit e8a7d50

File tree

4 files changed

+179
-62
lines changed

4 files changed

+179
-62
lines changed

sources/scala/xml/NodeTraverser.scala

+18-7
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,26 @@ package scala.xml ;
1111

1212
import scala.collection.mutable ;
1313

14-
abstract class NodeTraverser[A](handle: parsing.MarkupHandler[A]) {
14+
class NodeTraverser[A](handle: parsing.MarkupHandler[A]) {
1515

16-
def traverse(n: Node): Iterable[A] = {
17-
val nb = new mutable.ArrayBuffer[A]();
18-
val it = n.child.elements;
19-
while(it.hasNext) {
20-
nb.appendAll(traverse(it.next));
21-
}
16+
def traverse(n: Node): Iterable[A] = n match {
17+
case Text(t) => handle.text(0,t);
18+
case ProcInstr(ta,te) => handle.procInstr(0,ta,te);
19+
case Comment(t) => handle.comment(0,t);
20+
case CharData(cd) => handle.charData(0,cd);
21+
case EntityRef(n) => handle.entityRef(0,n);
22+
case _ =>
23+
val nb = new mutable.ArrayBuffer[A]();
24+
val it = n.child.elements;
25+
while(it.hasNext) {
26+
nb.appendAll(traverse(it.next));
27+
}
2228
handle.element(0, n.namespace, n.label, n.attributes.toMap, nb)
2329
}
2430

2531
}
32+
33+
class NodeSubstitution(handle: parsing.ConstructingHandler)
34+
extends NodeTraverser[Node](handle) with Function1[Node,Iterable[Node]] {
35+
def apply(n: Node) = traverse(n);
36+
}

sources/scala/xml/PrettyPrinter.scala

+107-9
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,21 @@ class PrettyPrinter( width:Int, step:Int ) {
102102
sb.toString();
103103
}
104104

105+
protected def rootStartTag(n: Node) = {
106+
val sb = new StringBuffer("<");
107+
Utility.appendPrefixedName( n.namespace, n.label, pmap, sb );
108+
Utility.attr2xml( n.namespace, n.attributes.elements, pmap, sb );
109+
if(( pmap.size != 1 )|| !pmap.contains(""))
110+
for( val c <- pmap.elements ) {
111+
sb.append(" xmlns:");
112+
sb.append(c._2);
113+
sb.append("=\"");
114+
sb.append(c._1);
115+
sb.append('"');
116+
}
117+
sb.append('>');
118+
sb.toString();
119+
}
105120
protected def startTag(n: Node) = {
106121
val sb = new StringBuffer("<");
107122
Utility.appendPrefixedName( n.namespace, n.label, pmap, sb );
@@ -110,6 +125,13 @@ class PrettyPrinter( width:Int, step:Int ) {
110125
sb.toString();
111126
}
112127

128+
protected def endTag(n: Node) = {
129+
val sb = new StringBuffer("</");
130+
Utility.appendPrefixedName( n.namespace, n.label, pmap, sb );
131+
sb.append('>');
132+
sb.toString();
133+
}
134+
113135
/** appends a formatted string containing well-formed XML with
114136
* given namespace to prefix mapping to the given stringbuffer
115137
* @param n the node to be serialized
@@ -119,7 +141,7 @@ class PrettyPrinter( width:Int, step:Int ) {
119141
def format(n: Node, pmap: Map[String,String], sb: StringBuffer ): Unit = {
120142
reset();
121143
this.pmap = pmap;
122-
traverse( n, 0 );
144+
traverse1( n, 0 );
123145
var cur = 0;
124146
//Console.println( items.reverse );
125147
for( val b <- items.reverse ) b match {
@@ -154,35 +176,111 @@ class PrettyPrinter( width:Int, step:Int ) {
154176
makeBox( ind, node.toString() );
155177

156178
case _:Node =>
157-
val test = node.toString();
158-
159-
if( ( test.length() < width - cur ) // all ?
160-
&&( !breakable( node ))) {
179+
val sb = new StringBuffer();
180+
val test = { Utility.toXML1(node,pmap,sb); sb.toString()};
181+
if(( test.length() < width - cur )&&( !breakable( node ))){ // all ?
161182
makeBox( ind, test );
162183
} else { // start tag + content + end tag
163184
//Console.println(node.label+" ind="+ind);
164185
val stg = startTag( node );
165-
val endTag = "</"+node.label+">";
166-
val len2 = node.label.length() + 1;
186+
val etg = endTag( node );
187+
val len2 = pmap(node.namespace).length() + node.label.length() + 2;
167188

168189
if( stg.length() < width - cur ) { // start tag fits
169190

170191
makeBox( ind, stg );
171192
makeBreak();
172193
traverse( node.child.elements, ind + step );
173-
makeBox( ind, endTag );
194+
makeBox( ind, etg );
174195

175196
} else if( len2 < width - cur ) {
176197
// <start label + attrs + tag + content + end tag
177198
makeBox( ind, stg.substring( 0, len2 ));
178199
makeBreak();
200+
/*{ //@todo
201+
val sq:Seq[String] = stg.split(" ");
202+
val it = sq.elements;
203+
it.next;
204+
for( val c <- it ) {
205+
makeBox( ind+len2-2, c );
206+
makeBreak();
207+
}
208+
}*/
179209
makeBox( ind, stg.substring( len2, stg.length() ));
180210
makeBreak();
181211
traverse( node.child.elements, ind + step );
182-
makeBox( cur, endTag );
212+
makeBox( cur, etg );
213+
} else {
214+
makeBox( ind, test );
215+
makeBreak();
183216
}
184217
}
218+
}
219+
}
220+
221+
/** @param tail: what we'd like to sqeeze in */
222+
protected def traverse1( node:Node, ind:int ):Unit = {
223+
node match {
224+
225+
case _:Text | _:CharData | _:Comment | _:EntityRef | _:ProcInstr =>
226+
makeBox( ind, node.toString() );
227+
228+
case _:Node => {
229+
// start tag + content + end tag
230+
//Console.println(node.label+" ind="+ind);
231+
val stg = rootStartTag( node );
232+
val etg = endTag( node );
233+
val len2 = pmap(node.namespace).length() +node.label.length() + 2;
234+
235+
if( stg.length() < width - cur ) { // start tag fits
236+
237+
makeBox( ind, stg );
238+
makeBreak();
239+
traverse( node.child.elements, ind + step );
240+
makeBox( ind, etg );
241+
242+
} else if( len2 < width - cur ) {
243+
val sq:Seq[String] = stg.split(" ");
244+
val it = sq.elements;
245+
var tmp = it.next;
246+
makeBox( ind, tmp );
247+
var curlen = cur + tmp.length();
248+
while( it.hasNext ) {
249+
var tmp = it.next;
250+
if( tmp.length() + curlen + 1 < width ) {
251+
makeBox( ind, " " );
252+
makeBox( ind, tmp );
253+
curlen = curlen + tmp.length() + 1;
254+
} else {
255+
makeBreak();
256+
makeBox( len2+1, tmp );
257+
curlen = len2+1;
258+
}
259+
}
260+
// <start label + attrs + tag + content + end tag
261+
//makeBox( ind, stg.substring( 0, len2 ));
262+
//makeBreak();
263+
/*{ //@todo
264+
val sq:Seq[String] = stg.split(" ");
265+
val it = sq.elements;
266+
it.next;
267+
for( val c <- it ) {
268+
makeBox( ind+len2-2, c );
269+
makeBreak();
270+
}
271+
}*/
272+
//makeBox( ind, stg.substring( len2, stg.length() ));
273+
makeBreak();
274+
traverse( node.child.elements, ind + step );
275+
makeBox( cur, etg );
276+
} else { // it does not fit, dump everything
277+
val sb = new StringBuffer();
278+
val tmp = { Utility.toXML1(node,pmap,sb); sb.toString()};
279+
makeBox( ind, tmp );
280+
makeBreak();
281+
}
185282
}
283+
}
186284
}
187285

188286
protected def traverse( it:Iterator[Node], ind:int ):unit = {

sources/scala/xml/Utility.scala

+53-45
Original file line numberDiff line numberDiff line change
@@ -131,59 +131,67 @@ object Utility {
131131
** with the given namespace prefix mapping
132132
* @param n the root node
133133
*/
134-
def toXML( x:Node, pmap:Map[String,String], sb:StringBuffer ):Unit = x match {
135-
case Text( t ) =>
136-
sb.append( escape( t ) );
137-
case _ if x.typeTag$ < 0 =>
138-
sb.append( x.toString() );
139-
case _ => {
140-
sb.append('<');
141-
appendPrefixedName( x.namespace, x.label, pmap, sb );
142-
if( x.attributes.length != 0 ) {
143-
attr2xml( x.namespace, x.attributes.elements, pmap, sb )
144-
}
145-
if( (pmap.size != 1)||pmap.get("").isEmpty) {
146-
for( val Pair(ns,pref) <- pmap.elements ) {
147-
sb.append(' ');
148-
sb.append("xmlns");
149-
if( pref.length() > 0 ) sb.append(':');
150-
sb.append(pref);
151-
sb.append("=\"");
152-
sb.append(ns);
153-
sb.append('"')
154-
}
155-
}
156-
sb.append('>');
157-
for( val c <- x.child.elements ) {
158-
toXML1( c, pmap, sb );
134+
def toXML( x:Node, pmap:Map[String,String], sb:StringBuffer ):Unit = {
135+
x match {
136+
case Text( t ) =>
137+
sb.append( escape( t ) );
138+
case _ if x.typeTag$ < 0 =>
139+
sb.append( x.toString() );
140+
case _ => {
141+
sb.append('<');
142+
appendPrefixedName( x.namespace, x.label, pmap, sb );
143+
if( x.attributes.length != 0 ) {
144+
attr2xml( x.namespace, x.attributes.elements, pmap, sb )
145+
}
146+
if( (pmap.size != 1)||pmap.get("").isEmpty) {
147+
for( val Pair(ns,pref) <- pmap.elements ) {
148+
sb.append(' ');
149+
sb.append("xmlns");
150+
if( pref.length() > 0 ) sb.append(':');
151+
sb.append(pref);
152+
sb.append("=\"");
153+
sb.append(ns);
154+
sb.append('"')
155+
}
156+
}
157+
sb.append('>');
158+
for( val c <- x.child.elements ) {
159+
toXML1( c, pmap, sb );
160+
}
161+
sb.append("</");
162+
appendPrefixedName( x.namespace, x.label, pmap, sb );
163+
sb.append('>');
159164
}
160-
sb.append("</");
161-
appendPrefixedName( x.namespace, x.label, pmap, sb );
162-
sb.append('>');
163165
}
164166
}
165167
/** serializes a tree to the given stringbuffer
166168
** with the given namespace prefix mapping
167169
* @param n the root node
168170
*/
169-
def toXML1( x:Node, pmap:Map[String,String], sb:StringBuffer ):Unit = x match {
170-
case Text( t ) =>
171-
sb.append( escape( t ) );
172-
case _ if x.typeTag$ < 0 =>
173-
sb.append( x.toString() );
174-
case _ => {
175-
sb.append('<');
176-
appendPrefixedName( x.namespace, x.label, pmap, sb );
177-
if( x.attributes.length != 0 ) {
178-
attr2xml( x.namespace, x.attributes.elements, pmap, sb )
179-
}
180-
sb.append('>');
181-
for( val c <- x.child.elements ) {
182-
toXML1( c, pmap, sb );
171+
def toXML1( x:Node, pmap:Map[String,String], sb:StringBuffer ):Unit = {
172+
//Console.print("toString: "+x.toString());
173+
x match {
174+
case Text( t ) =>
175+
//Console.println("case Text");
176+
sb.append( escape( t ) );
177+
case _ if x.typeTag$ < 0 =>
178+
//Console.println("case _ if tag");
179+
sb.append( x.toString() );
180+
case _ => {
181+
//Console.println("case _, class"+x.getClass());
182+
sb.append('<');
183+
appendPrefixedName( x.namespace, x.label, pmap, sb );
184+
if( x.attributes.length != 0 ) {
185+
attr2xml( x.namespace, x.attributes.elements, pmap, sb )
186+
}
187+
sb.append('>');
188+
for( val c <- x.child.elements ) {
189+
toXML1( c, pmap, sb );
190+
}
191+
sb.append("</");
192+
appendPrefixedName( x.namespace, x.label, pmap, sb );
193+
sb.append('>');
183194
}
184-
sb.append("</");
185-
appendPrefixedName( x.namespace, x.label, pmap, sb );
186-
sb.append('>');
187195
}
188196
}
189197

sources/scala/xml/parsing/ConstructingHandler.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class ConstructingHandler extends MarkupHandler[Node] {
1010

1111
//def attributeNamespaceDecl(pos: int, uri: String) = NamespaceDecl(uri);
1212

13-
def element(pos: int, uri: String, label: String, attrMap1: Map[Pair[String,String],Attribute], args: mutable.Buffer[Node]) = {
13+
def element(pos: int, uri: String, label: String, attrMap1: Map[Pair[String,String],Attribute], args: mutable.Buffer[Node]):Iterable[Node] = {
1414

1515
var attrs = new Array[Attribute](attrMap1.size);
1616
{

0 commit comments

Comments
 (0)