summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorburaq <buraq@epfl.ch>2004-10-12 10:13:22 +0000
committerburaq <buraq@epfl.ch>2004-10-12 10:13:22 +0000
commitb687aa18830420485d59e2c3c8151f38451e48f0 (patch)
treea1e09ce5d995dafcc057cdd949bf922389731139
parent60e78ebb8c4767b197da1b06e90f0e4e9edb7798 (diff)
downloadscala-b687aa18830420485d59e2c3c8151f38451e48f0.tar.gz
scala-b687aa18830420485d59e2c3c8151f38451e48f0.tar.bz2
scala-b687aa18830420485d59e2c3c8151f38451e48f0.zip
fixes, changes, add Node::toString(stripComments)
-rw-r--r--sources/scala/xml/BindingFactoryAdapter.scala27
-rw-r--r--sources/scala/xml/Node.scala89
-rw-r--r--sources/scala/xml/Utility.scala167
3 files changed, 148 insertions, 135 deletions
diff --git a/sources/scala/xml/BindingFactoryAdapter.scala b/sources/scala/xml/BindingFactoryAdapter.scala
index 8468024106..698be8b82c 100644
--- a/sources/scala/xml/BindingFactoryAdapter.scala
+++ b/sources/scala/xml/BindingFactoryAdapter.scala
@@ -18,6 +18,8 @@ import scala.collection.mutable.HashMap ;
abstract class BindingFactoryAdapter extends FactoryAdapter() {
+ var errors = 0;
+
/** mapping from element names to an element constructor
* (constr:Seq[Node],HashMap[String,String] => Node)
*/
@@ -32,24 +34,41 @@ abstract class BindingFactoryAdapter extends FactoryAdapter() {
val compress: boolean ;
/** looks up whether an element may have text children */
- def nodeContainsText( name:java.lang.String ):boolean = g( name );
+ def nodeContainsText( name:java.lang.String ):boolean = {
+ g.get( name ) match {
+ case Some(x) => x;
+ case _ =>
+ errors = errors + 1;
+ java.lang.System.err.println(
+ "[unrecognized element \""+name+"\"]"
+ );true
+ }
+ }
// if compress is set, used for hash-consing
val cache = new HashMap[int,Node];
//var cacheCount = 0;
+
+ def getConstructor(elemName: String) =
+ f.get( elemName ) match {
+ case Some(d) => d
+ case _ => {
+ throw new IllegalArgumentException("unrecognized:elemNamehello");
+ }
+ }
+
/** creates an element. see also compress */
def createNode(uri:String,
elemName:String,
attribs:HashMap[Pair[String,String],String],
children:List[Node] ):Node = {
-
val uri$ = uri.intern();
val attribs1 = AttributeSeq.fromMap(attribs);
// 2do:optimize
if( !compress ) {
// get constructor
- val c = f( elemName );
+ val c = getConstructor(elemName);
c( attribs1, children );
} else { // do hash-consing
@@ -64,7 +83,7 @@ abstract class BindingFactoryAdapter extends FactoryAdapter() {
case None =>
// get constructor
- val c = f( elemName );
+ val c = getConstructor( elemName );
val el = c( attribs1, children );
cache.update( h, el );
el
diff --git a/sources/scala/xml/Node.scala b/sources/scala/xml/Node.scala
index 8dd58440e7..0f8eb8535b 100644
--- a/sources/scala/xml/Node.scala
+++ b/sources/scala/xml/Node.scala
@@ -26,42 +26,34 @@ object Node {
*/
abstract class Node extends NodeSeq {
- final def theSeq = this :: Nil;
- /*
- final def length = 1;
- final def elements = new Iterator[Node] {
- var notAccessed = true;
- final def hasNext = notAccessed;
- final def next = {notAccessed = false; Node.this}
- }
- final def apply(i: Int) = if( i==0 ) this else error("singleton sequence");
- */
-
- /** used internally. Text = -1 PI = -2 Comment = -3 CDATA = -4 EntityRef = -5
- */
- def typeTag$:Int = 0;
+ private var internalAttrMap:Map[String, String] = null;
- /** QName (the label of this node). I.e. "foo" for &lt;foo/&gt;) */
+ /** label of this node. I.e. "foo" for &lt;foo/&gt;) */
def label: String;
/** the namespace of this node */
def namespace: String;
- private var internalAttrMap:Map[String, String] = null;
+ /** used internally. Text = -1 PI = -2 Comment = -3 CDATA = -4 EntityRef = -5 */
+ def typeTag$:Int = 0;
/** attribute map for attributes with the same namespace as this element */
final def attribute: Map[String,String] = {
if( internalAttrMap == null )
internalAttrMap = new Map[String,String] {
val theMap = new collection.mutable.HashMap[String,String];
- theMap ++=
- attributes.elements
- .filter( x => x.namespace == namespace )
- .map( x => Pair(x.key, x.value) );
-
- def size = theMap.size;
- def elements = theMap.elements;
- def get(x:String) = theMap.get(x);
+ theMap ++= attributes.elements
+ .filter( x => x.namespace == namespace )
+ .map( x => Pair(x.key, x.value) );
+
+ def size =
+ theMap.size;
+
+ def elements =
+ theMap.elements;
+
+ def get(x:String) =
+ theMap.get(x);
};
internalAttrMap
}
@@ -74,13 +66,13 @@ abstract class Node extends NodeSeq {
def child: Seq[Node];
/** descendant axis (all descendants of this node) */
- def descendant:List[Node] = child.toList.flatMap {
- x => x::x.descendant
- } ;
+ def descendant:List[Node] =
+ child.toList.flatMap { x => x::x.descendant } ;
/** descendant axis (all descendants of this node) */
def descendant_or_self:List[Node] = this :: descendant;
+ /** structural equality */
override def equals( x:Any ):boolean = x match {
case that:Node =>
//Console.print("(Node)");
@@ -90,36 +82,23 @@ abstract class Node extends NodeSeq {
case _ => false
}
- /** projection function. Similar to XPath, use this \ 'foo to get a list
- * of all children of this node that are labelled with "foo".
- * The document order is preserved.
- def \( that:String ): NodeSeq = that match {
-
- case "_" => new NodeSeq { val theSeq = child; }
- case _ =>
- var res:List[Node] = Nil;
- for( val x <- child.elements; x.label == that ) {
- res = x::res;
- }
- new NodeSeq { val theSeq = res.reverse }
- }
- */
+ /** returns a hashcode */
+ override def hashCode() =
+ Utility.hashCode(namespace, label, attribute.toList.hashCode(), child);
- /** projection function. Similar to XPath, use this \\ 'foo to filter
- * all nodes labelled with "foo" from the descendant_or_self axis.
- * The document order is preserved.
- def \\( that:String ): NodeSeq = {
- val z = this.descendant_or_self;
- new NodeSeq(
- that match {
- case "_" => z
- case _ => z.filter( x => x.label == that );
- })
- }
+
+ /** method for NodeSeq */
+ final def theSeq = this :: Nil;
+
+ /** string representation of this node
+ * @param stripComment if true, strips comment nodes from result
*/
+ def toString(stripComment: Boolean): String =
+ Utility.toXML(this, stripComment);
- override def hashCode() = Utility.hashCode(namespace, label, attribute.toList.hashCode(), child);
- /** string representation of this node */
- override def toString() = Utility.toXML(this);
+ /** @see toString(false)
+ */
+ override def toString(): String =
+ toString(false);
}
diff --git a/sources/scala/xml/Utility.scala b/sources/scala/xml/Utility.scala
index 6ac96995dd..6c538109a9 100644
--- a/sources/scala/xml/Utility.scala
+++ b/sources/scala/xml/Utility.scala
@@ -20,12 +20,10 @@ import scala.collection.Map ;
object Utility {
- def view( s:String ):Text = Text( s );
+ def view(s: String): Text = Text(s);
- /** representation of text in a string that is well-formed XML.
- ** the characters &lt; &gt; &amp; and &quot; are escaped
- */
- def escape( text:String ) = {
+ /* escapes the characters &lt; &gt; &amp; and &quot; from string */
+ def escape(text: String) = {
val s = new StringBuffer();
for (val c <- Iterator.fromString(text)) c match {
case '<' => s.append("&lt;");
@@ -69,13 +67,13 @@ object Utility {
return set;
}
/** a prefix mapping that maps the empty namespace to the empty prefix */
- val noPrefixes:Map[String,String] =
+ val noPrefixes: Map[String,String] =
immutable.ListMap.Empty[String,String].update("","");
/** returns a default prefix mapping for a set of namespaces.
* the empty namespace is mapped to the empty prefix
*/
- def defaultPrefixes(rootns:String,nset:mutable.Set[String]):Map[String,String] = {
+ def defaultPrefixes(rootns: String, nset: mutable.Set[String]): Map[String,String] = {
val map = new mutable.HashMap[String,String]();
if( nset.contains("http://www.w3.org/XML/1998/namespace"))
map.update("http://www.w3.org/XML/1998/namespace","xml");
@@ -91,57 +89,70 @@ object Utility {
return map;
}
- /** same as defaultPrefixes(n.namespace, collectNamespaces( n )) */
- def defaultPrefixes( n:Node ):Map[String,String] =
+ /** @see defaultPrefixes(n.namespace, collectNamespaces( n )) */
+ def defaultPrefixes(n: Node): Map[String,String] =
defaultPrefixes(n.namespace, collectNamespaces( n ));
- /** same as defaultPrefixes("", ncollectNamespaces( nodes )) */
- def defaultPrefixes(nodes: Seq[Node]): Map[String,String] = {
+ /** @see defaultPrefixes("", ncollectNamespaces( nodes )) */
+ def defaultPrefixes(nodes: Seq[Node]): Map[String,String] =
defaultPrefixes("", collectNamespaces( nodes ));
- }
- /** serializes an instance of Node to a string that contains well-formed XML
+
+ /** @see toXML(n, true)
+ */
+ def toXML(n: Node): String = toXML(n, true);
+
+ /** string representation of a Node. uses namespace mapping from defaultPrefixes( n ).
* @todo define a way to escape literal characters to &amp;xx; references
*/
- def toXML(n: Node): String = n match {
- case Text( t ) =>
- escape( t );
- case _ if n.typeTag$ < 0 =>
- n.toString();
- case _ =>
- val s = new StringBuffer();
- toXML( n, defaultPrefixes( n ), s );
- s.toString();
+ def toXML(n: Node, stripComment: Boolean): String = {
+ val s = new StringBuffer();
+ toXML(n, defaultPrefixes( n ), s, stripComment);
+ s.toString();
}
+ /** @see toXML(x, pmap, false) */
+ def toXML(x: Node, pmap:Map[String,String]): String =
+ toXML(x, pmap, false);
+
/** serializes a node with given namespace prefix mapping. the prefix
* mapping may not map the empty namespace "" to some non-empty prefix.
* @arg n the node to serialize
* @pmap a mapping from namespace URIs to prefixes
*/
- def toXML(x: Node, pmap:Map[String,String] ):String = x match {
- case Text( t ) =>
- escape( t );
- case _ if x.typeTag$ < 0 =>
- x.toString();
- case _ =>
- val sb = new StringBuffer();
- toXML( x, pmap, sb );
- sb.toString();
+ def toXML(x: Node, pmap:Map[String,String], stripComment: Boolean): String = {
+ val sb = new StringBuffer();
+ toXML( x, pmap, sb, stripComment );
+ sb.toString();
}
+ /** @see toXML(x,pmap,sb,false) */
+ def toXML(x:Node, pmap:Map[String,String], sb:StringBuffer):Unit =
+ toXML(x, pmap, sb, false);
+
/** serializes a tree to the given stringbuffer
- ** with the given namespace prefix mapping
- * @param n the root node
- */
- def toXML( x:Node, pmap:Map[String,String], sb:StringBuffer ):Unit = {
+ * with the given namespace prefix mapping.
+ * elements and attributes that have namespaces not in pmap are <string>ignored</string>
+ * @param n the root node
+ * @param pmap mapping namespaces to prefixes
+ * @param sb stringbuffer to append to
+ * @param stripComment if true, strip comments
+ */
+ def toXML(x: Node, pmap: Map[String,String], sb: StringBuffer, stripComment: Boolean): Unit = {
x match {
+
case Text( t ) =>
- sb.append( escape( t ) );
+ sb.append(escape( t ));
+
+ case Comment( text ) =>
+ if(stripComment) text else "";
+
case _ if x.typeTag$ < 0 =>
sb.append( x.toString() );
- case _ => {
+
+ case _ if( pmap.contains( x.namespace )) => {
+ // print tag with namespace declarations
sb.append('<');
appendPrefixedName( x.namespace, x.label, pmap, sb );
if( x.attributes.length != 0 ) {
@@ -151,7 +162,7 @@ object Utility {
for( val Pair(ns,pref) <- pmap.elements; pref!="xml" ) {
sb.append(' ');
sb.append("xmlns");
- if( pref.length() > 0 ) sb.append(':');
+ if(pref.length() > 0) sb.append(':');
sb.append(pref);
sb.append("=\"");
sb.append(ns);
@@ -160,7 +171,7 @@ object Utility {
}
sb.append('>');
for( val c <- x.child.elements ) {
- toXML1( c, pmap, sb );
+ toXML1( c, pmap, sb, stripComment );
}
sb.append("</");
appendPrefixedName( x.namespace, x.label, pmap, sb );
@@ -168,21 +179,28 @@ object Utility {
}
}
}
- /** serializes a tree to the given stringbuffer
- ** with the given namespace prefix mapping
- * @param n the root node
- */
- def toXML1( x:Node, pmap:Map[String,String], sb:StringBuffer ):Unit = {
+
+ /** serializes a non-root node to the given stringbuffer
+ * with the given namespace prefix mapping. use toXML to print the root node, which
+ * will have namespace declarations.
+ * @param n the non-root node
+ * @param pmap mapping namespaces to prefixes
+ * @param sb stringbuffer to append to
+ * @param stripComment if true, strip comments
+ */
+ def toXML1(x:Node, pmap:Map[String,String], sb:StringBuffer, stripComment:Boolean): Unit = {
//Console.print("toString: "+x.toString());
x match {
case Text( t ) =>
- //Console.println("case Text");
sb.append( escape( t ) );
+
+ case Comment( text ) =>
+ if(stripComment) text else "";
+
case _ if x.typeTag$ < 0 =>
- //Console.println("case _ if tag");
sb.append( x.toString() );
- case _ => {
- //Console.println("case _, class"+x.getClass());
+
+ case _ if( pmap.contains( x.namespace )) => {
sb.append('<');
appendPrefixedName( x.namespace, x.label, pmap, sb );
if( x.attributes.length != 0 ) {
@@ -190,7 +208,7 @@ object Utility {
}
sb.append('>');
for( val c <- x.child.elements ) {
- toXML1( c, pmap, sb );
+ toXML1( c, pmap, sb, stripComment );
}
sb.append("</");
appendPrefixedName( x.namespace, x.label, pmap, sb );
@@ -199,56 +217,53 @@ object Utility {
}
}
- /*
- def toXML( ch:Iterator[Node] ):String = {
- ch.foldLeft ("") { (s:String,n:Node) => s + n.toString() }
- }
-*/
+ /** see toXML1(x,pmap,sb,false); */
+ def toXML1(x:Node, pmap:Map[String,String], sb:StringBuffer): Unit =
+ toXML1(x,pmap,sb,false);
+
/** for a Node n, returns string representation of n.attributes **/
- def attr2xml( ns:String, attrib: Iterator[Attribute], pmap: Map[String, String], sb: StringBuffer ):Unit = {
+ def attr2xml(ns: String, attrib: Iterator[Attribute], pmap: Map[String, String], sb: StringBuffer ) = {
for( val x <- attrib ) {
- sb.append( " " );
+ sb.append(' ');
if( ns == x.namespace )
- sb.append( x.key );
- else
- appendPrefixedName( x.namespace, x.key, pmap, sb );
+ sb.append( x.key );
+ else
+ appendPrefixedName( x.namespace, x.key, pmap, sb );
sb.append("=");
appendQuoted(x.value, sb)
}
}
/** returns a hashcode for the given constituents of a node */
- def hashCode(uri:String, label:String, attribHashCode:int, children:Seq[Node]) = {
+ def hashCode(uri: String, label: String, attribHashCode: Int, children: Seq[Node]) = {
41 * uri.hashCode() % 7 + label.hashCode() + attribHashCode + children.hashCode()
}
/** returns a hashcode for the given constituents of a node */
- def hashCode(uri:String, label:String, attribs:scala.collection.mutable.HashMap[Pair[String,String],String], children:Seq[Node]) = {
+ def hashCode(uri: String, label: String, attribs: scala.collection.mutable.HashMap[Pair[String,String],String], children: Seq[Node]): Int = {
41 * uri.hashCode() % 7 + label.hashCode() + attribs.toList.hashCode() + children.hashCode()
}
- def systemLiteralToString( s:String ) = {
+ def systemLiteralToString(s: String) = {
val sb = new StringBuffer("SYSTEM ");
appendQuoted(s, sb);
sb.toString();
}
- def publicLiteralToString( s:String ) = {
+ def publicLiteralToString(s: String) = {
val sb = new StringBuffer("PUBLIC ");
sb.append('"').append(s).append('"');
sb.toString();
}
-
-
- def appendPrefixedName( ns: String, name: String, pmap: Map[String, String], sb: StringBuffer ):Unit = {
- pmap.get( ns ) match {
- case Some( pref ) =>
- if( pref.length() > 0 ) {
- sb.append( pref );
- sb.append(':');
- }
- case None => error("no prefix found for namespace \""+ns+"\"");
+ /** appends prefixed name to given stringbuffer using namespace-to-prefix mapping pmap.
+ * precondition: pmap.contains(ns)
+ */
+ def appendPrefixedName(ns: String, name: String, pmap: Map[String, String], sb: StringBuffer): Unit = {
+ val pref = pmap( ns );
+ if( pref.length() > 0 ) {
+ sb.append( pref );
+ sb.append(':');
}
sb.append( name );
}
@@ -256,13 +271,13 @@ object Utility {
/** appends &quot;s&quot; if s does not contain &quot;, &apos;s&apos;
* otherwise
*/
- def appendQuoted( s:String, sb:StringBuffer ):Unit = {
- val ch = { if( s.indexOf('"') == -1 ) '"' else '\''}
+ def appendQuoted( s:String, sb:StringBuffer ) = {
+ val ch = if( s.indexOf('"') == -1 ) '"' else '\'';
sb.append(ch).append(s).append(ch);
}
/** appends &quot;s&quot; and escapes and &quot; i s with \&quot; */
- def appendEscapedQuoted( s:String, sb:StringBuffer ):Unit = {
+ def appendEscapedQuoted( s:String, sb:StringBuffer ) = {
sb.append('"');
val z:Seq[Char] = s;
for( val c <- z ) c match {