diff options
author | buraq <buraq@epfl.ch> | 2005-04-24 22:19:29 +0000 |
---|---|---|
committer | buraq <buraq@epfl.ch> | 2005-04-24 22:19:29 +0000 |
commit | 67290d08794a237841dca5cfcb3fda7c05d22cdf (patch) | |
tree | d8cbdc226b49d80b18d0f6106fb2a5969fcacbe8 | |
parent | 6d081b3c4c6647386bd1b113e50d6285ff81aa99 (diff) | |
download | scala-67290d08794a237841dca5cfcb3fda7c05d22cdf.tar.gz scala-67290d08794a237841dca5cfcb3fda7c05d22cdf.tar.bz2 scala-67290d08794a237841dca5cfcb3fda7c05d22cdf.zip |
rearrangement of Scala XML library
-rw-r--r-- | config/list/library.lst | 14 | ||||
-rw-r--r-- | sources/scala/xml/Comment.scala | 20 | ||||
-rw-r--r-- | sources/scala/xml/Elem.scala | 5 | ||||
-rw-r--r-- | sources/scala/xml/EntityRef.scala | 25 | ||||
-rw-r--r-- | sources/scala/xml/FactoryAdapter.scala | 345 | ||||
-rw-r--r-- | sources/scala/xml/LoggedNodeFactory.scala | 78 | ||||
-rw-r--r-- | sources/scala/xml/Node.scala | 14 | ||||
-rw-r--r-- | sources/scala/xml/NodeFactory.scala | 77 | ||||
-rw-r--r-- | sources/scala/xml/ProcInstr.scala | 33 | ||||
-rw-r--r-- | sources/scala/xml/SpecialNode.scala | 13 | ||||
-rw-r--r-- | sources/scala/xml/Text.scala | 16 | ||||
-rw-r--r-- | sources/scala/xml/Utility.scala | 97 | ||||
-rw-r--r-- | sources/scala/xml/nobinding/NoBindingFactoryAdapter.scala | 61 | ||||
-rw-r--r-- | sources/scala/xml/nobinding/XML.scala | 76 | ||||
-rw-r--r-- | test/files/jvm/xml01.scala | 112 | ||||
-rw-r--r-- | test/files/jvm/xmlstuff.scala | 3 |
16 files changed, 167 insertions, 822 deletions
diff --git a/config/list/library.lst b/config/list/library.lst index 2c32d8662f..4412243468 100644 --- a/config/list/library.lst +++ b/config/list/library.lst @@ -215,17 +215,12 @@ util/logging/Logged.scala util/logging/ConsoleLogger.scala xml/Comment.scala -xml/DocType.scala xml/Elem.scala xml/EntityRef.scala -xml/ExternalID.scala -xml/FactoryAdapter.scala -xml/LoggedNodeFactory.scala xml/MetaData.scala xml/NamespaceBinding.scala xml/Node.scala xml/NodeBuffer.scala -xml/NodeFactory.scala xml/NodeSeq.scala #xml/NodeTraverser.scala xml/Null.scala @@ -239,23 +234,28 @@ xml/TextBuffer.scala xml/TopScope.scala xml/UnprefixedAttribute.scala xml/Utility.scala +xml/XML.scala xml/dtd/ContentModel.scala +xml/dtd/DocType.scala xml/dtd/Decl.scala +xml/dtd/ExternalID.scala xml/dtd/Parser.scala xml/dtd/Scanner.scala xml/dtd/Tokens.scala xml/dtd/Validation.scala xml/dtd/ValidationException.scala -xml/nobinding/NoBindingFactoryAdapter.scala -xml/nobinding/XML.scala +xml/factory/NodeFactory.scala +xml/factory/LoggedNodeFactory.scala xml/parsing/ConstructingHandler.scala xml/parsing/ConstructingParser.scala xml/parsing/FatalError.scala xml/parsing/MarkupHandler.scala xml/parsing/MarkupParser.scala +xml/parsing/FactoryAdapter.scala +xml/parsing/NoBindingFactoryAdapter.scala xml/path/Expression.scala xml/transform/BasicTransformer.scala diff --git a/sources/scala/xml/Comment.scala b/sources/scala/xml/Comment.scala index 2b646ad001..d075fdad77 100644 --- a/sources/scala/xml/Comment.scala +++ b/sources/scala/xml/Comment.scala @@ -15,27 +15,29 @@ import scala.collection.immutable ; * * @author Burak Emir * @param text text contained in this node, may not contain "--" -**/ + */ -case class Comment( text:String ) extends SpecialNode { +case class Comment(text: String) extends SpecialNode { final override def typeTag$:Int = -3; if( text.indexOf("--" ) != -1 ) throw new IllegalArgumentException("text containts \"--\""); - final override def equals(x:Any) = x match { - case Comment( s ) => text.equals( s ); - case _ => false; + /** structural equality */ + override def equals(x: Any): Boolean = x match { + case Comment(x) => x.equals(text); + case _ => false } - /** the constant "#REM" */ + /** the constant "#REM" */ def label = "#REM"; /** hashcode for this Comment */ override def hashCode() = text.hashCode(); - /** returns "<!--"+text+"-->" */ - final override def toString() = "<!--"+text+"-->"; - + /** appends "<!-- text -->" to this stringbuffer */ + def toString(sb: StringBuffer) = { + sb.append("<!--").append(text).append("-->") + } } diff --git a/sources/scala/xml/Elem.scala b/sources/scala/xml/Elem.scala index 747f0d5757..d4dc0c8ab9 100644 --- a/sources/scala/xml/Elem.scala +++ b/sources/scala/xml/Elem.scala @@ -23,7 +23,10 @@ import scala.collection.mutable.ArrayBuffer; // "val" is redundant for non-overriding arguments case class Elem(override val prefix:String, val label: String, override val attributes: MetaData, override val scope: NamespaceBinding, val child: Node*) extends Node { - if(null== scope) + if(prefix != null && 0 == prefix.length()) + error("prefix of zero length, use null instead"); + + if(null == scope) error("scope is null"); //@todo: copy the children, diff --git a/sources/scala/xml/EntityRef.scala b/sources/scala/xml/EntityRef.scala index a3de453c30..192cf85797 100644 --- a/sources/scala/xml/EntityRef.scala +++ b/sources/scala/xml/EntityRef.scala @@ -9,29 +9,30 @@ package scala.xml; -import scala.collection.immutable ; -/** an XML node for text (PCDATA). Used in both non-bound and bound XML - * representations - * @author Burak Emir +/** an XML node for entity references + * + * @author buraq * @param text the text contained in this node -**/ + **/ case class EntityRef( entityName:String ) extends SpecialNode { final override def typeTag$:Int = -5; + /** structural equality */ + override def equals(x: Any): Boolean = x match { + case EntityRef(x) => x.equals(entityName); + case _ => false + } + /** the constant "#ENTITY" */ def label = "#ENTITY"; - final override def equals(x:Any) = x match { - case EntityRef( s ) => entityName.equals( s ); - case _ => false; - } - override def hashCode() = entityName.hashCode(); - /** returns text, with some characters escaped according to XML spec */ - final override def toString():String = "&"+entityName+";"; + /** appends "& entityName;" to this stringbuffer */ + def toString(sb:StringBuffer) = + sb.append("&").append(entityName).append(";"); } diff --git a/sources/scala/xml/FactoryAdapter.scala b/sources/scala/xml/FactoryAdapter.scala deleted file mode 100644 index e120811269..0000000000 --- a/sources/scala/xml/FactoryAdapter.scala +++ /dev/null @@ -1,345 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -** $Id$ -\* */ -package scala.xml ; - -import java.io._ ; -import scala.collection.mutable.{HashMap,Stack}; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; - - -import org.xml.sax.ErrorHandler; -import org.xml.sax.Locator; -import org.xml.sax.InputSource; - -import org.xml.sax.SAXException; -import org.xml.sax.SAXNotRecognizedException; -import org.xml.sax.SAXNotSupportedException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; - -import javax.xml.parsers.SAXParserFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; - - -/** SAX adapter class, for use with Java SAX parser. Keeps track of - * namespace bindings, without relying on namespace handling of the - * underlying SAX parser. - */ -abstract class FactoryAdapter extends DefaultHandler() { - - val buffer = new StringBuffer(); - val attribStack = new Stack[MetaData]; - val hStack = new Stack[Node]; // [ element ] contains siblings - val tagStack = new Stack[String]; - var scopeStack = new Stack[NamespaceBinding]; - - var curTag : String = null ; - var capture:boolean = false; - - // abstract methods - - /** Tests if an XML element contains text. - * @return true if element named <code>localName</code> contains text. - */ - def nodeContainsText( localName:String ):boolean ; // abstract - - /** creates an new non-text(tree) node. - * @param elemName - * @param attribs - * @param chIter - * @return a new XML element. - */ - def createNode(pre: String, elemName: String, attribs: MetaData, scope: NamespaceBinding, chIter: List[Node] ):Node; //abstract - - /** creates a Text node. - * @param text - * @return a new Text node. - */ - def createText( text:String ):Text[String]; // abstract - - // - // ContentHandler methods - // - - val normalizeWhitespace = false; - - /** Characters. - * @param ch - * @param offset - * @param length - */ - override def characters(ch: Array[Char], offset: Int, length: Int): Unit = { - - if (capture) { - if( normalizeWhitespace ) { // normalizing whitespace is not compliant, but useful */ - var i:int = offset; - var ws:boolean = false; - while (i < offset + length) { - if ( Character.isWhitespace( ch(i) ) ) { - if (!ws) { - buffer.append(' '); - ws = true; - } - } else { - buffer.append(ch(i)); - ws = false; - } - i = i+1; - } - } else { // compliant:report every character - - buffer.append( ch, offset, length ); - - } - } - } - - //var elemCount = 0; //STATISTICS - - /* ContentHandler methods */ - - /* Start prefix mapping - use default impl. - def startPrefixMapping( prefix:String , uri:String ):Unit = {} - */ - - - - /* Start element. */ - override def startElement(uri:String, _localName:String, qname:String, attributes:Attributes ):Unit = { - /*elemCount = elemCount + 1; STATISTICS */ - captureText(); - //Console.println("FactoryAdapter::startElement("+uri+","+_localName+","+qname+","+attributes+")"); - tagStack.push(curTag); - curTag = qname; //localName ; - - val colon = qname.indexOf(':'); - val localName = if(-1 == colon) qname else qname.substring(colon+1,qname.length()); - - //Console.println("FactoryAdapter::startElement - localName ="+localName); - - capture = nodeContainsText(localName) ; - - hStack.push( null ); - var m: MetaData = Null; - - var scpe = scopeStack.top; - for( val i <- List.range( 0, attributes.getLength() )) { - //val attrType = attributes.getType(i); // unused for now - val qname = attributes.getQName(i); - val value = attributes.getValue(i); - val colon = qname.indexOf(':'); - if(-1 != colon) { // prefixed attribute - val pre = qname.substring(0, colon); - val key = qname.substring(colon+1, qname.length()); - if("xmlns" == pre) - scpe = value.length() match { - case 0 => new NamespaceBinding(key, null, scpe); - case _ => new NamespaceBinding(key, value, scpe); - } - else - m = new PrefixedAttribute(pre, key, value, m) - } else if("xmlns" == qname) - scpe = value.length() match { - case 0 => new NamespaceBinding(null, null, scpe); - case _ => new NamespaceBinding(null, value, scpe); - } - else - m = new UnprefixedAttribute(qname, value, m) - } - scopeStack.push(scpe); - attribStack.push( m ); - {} - } // startElement(String,String,String,Attributes) - - - /** captures text, possibly normalizing whitespace - */ - def captureText():Unit = { - if (capture == true) { - val text = buffer.toString(); - if(( text.length() > 0 )&&( !( text.equals(" ")))) { - val _ = hStack.push( createText( text ) ); - } - } - buffer.setLength(0); - } - - /** End element. - * @param uri - * @param localName - * @param qname - * @throws org.xml.sax.SAXException if .. - */ - override def endElement(uri:String , _localName:String , qname:String ):Unit = { - captureText(); - - val metaData = attribStack.pop; - - // reverse order to get it right - var v:List[Node] = Nil; - var child:Node = hStack.pop; - while( child != null ) { - v = child::v; - child = hStack.pop; - } - - val colon = qname.indexOf(':'); - val localName = if(-1 == colon) qname else qname.substring(colon+1,qname.length()); - - val scp = scopeStack.pop; - // create element - rootElem = if(-1 == colon) - createNode( null, localName, metaData, scp, v ); - else - createNode( qname.substring(0,colon), localName, metaData, scp, v ); - - hStack.push(rootElem); - - // set - curTag = tagStack.pop; - - if (curTag != null) // root level - capture = nodeContainsText(curTag); - else - capture = false; - - } // endElement(String,String,String) - - // - // ErrorHandler methods - // - - /** Warning.*/ - override def warning(ex:SAXParseException ):Unit = { - // ignore warning, crimson warns even for entity resolution! - //printError("Warning", ex); - } - /** Error. */ - override def error(ex:SAXParseException ):Unit = { - printError("Error", ex); - } - - /** Fatal error.*/ - override def fatalError(ex:SAXParseException ):Unit = { - printError("Fatal Error", ex); - } - - // - // Protected methods - // - - /** Prints the error message */ - protected def printError( errtype:String , ex:SAXParseException ):Unit = { - - System.err.print("["); - System.err.print(errtype); - System.err.print("] "); - - var systemId = ex.getSystemId(); - if (systemId != null) { - val index = systemId.lastIndexOf('/'); - if (index != -1) - systemId = systemId.substring(index + 1); - //System.err.print(systemId); - } - - System.err.print(':'); - System.err.print(ex.getLineNumber()); - System.err.print(':'); - System.err.print(ex.getColumnNumber()); - System.err.print(": "); - System.err.print(ex.getMessage()); - System.err.println(); - System.err.flush(); - - } - - var rootElem : Node = null:Node; - - //FactoryAdapter - // MAIN - // - - /** load XML document - * @param source - * @return a new XML document object - */ - def loadXML( source:InputSource ):Node = { - - // variables - var parser:SAXParser = null; - - // create parser - try { - val f = SAXParserFactory.newInstance(); - f.setNamespaceAware( false ); - parser = f.newSAXParser(); - } catch { - case ( e:Exception ) => { - System.err.println("error: Unable to instantiate parser"); - System.exit(-1); - } - } - - // parse file - try { - //System.err.println("[parsing \"" + source + "\"]"); - scopeStack.push(TopScope); - parser.parse( source, this ); - scopeStack.pop; - } catch { - case ( e:SAXParseException ) => { - // ignore - } - case ( e:Exception ) => { - System.err.println("error: Parse error occurred - " + e.getMessage()); - if (e.isInstanceOf[ SAXException ]) { - (e.asInstanceOf[ SAXException ]) - .getException() - .printStackTrace( System.err ); - } else { - e.printStackTrace(System.err); - } - } - } // catch - //System.err.println("[FactoryAdapter: total #elements = "+elemCount+"]"); - rootElem - - } // loadXML - - - - /** loads XML from given file */ - def loadFile( file:File ):Node = loadXML( new InputSource( - new FileInputStream( file ) - )); - - /** loads XML from given file descriptor */ - def loadFile( fileDesc:FileDescriptor ):Node = loadXML( new InputSource( - new FileInputStream( fileDesc ) - )); - - /** loads XML from given file */ - def loadFile( fileName:String ):Node = loadXML( new InputSource( - new FileInputStream( fileName ) - )); - - /** loads XML from given InputStream */ - def load( is:InputStream ):Node = loadXML( new InputSource( is )); - - /** loads XML from given Reader */ - def load( reader:Reader ):Node = loadXML( new InputSource( reader )); - - /** loads XML from given sysID */ - def load( sysID:String ):Node = loadXML( new InputSource( sysID )); - -} diff --git a/sources/scala/xml/LoggedNodeFactory.scala b/sources/scala/xml/LoggedNodeFactory.scala deleted file mode 100644 index e838b1b56c..0000000000 --- a/sources/scala/xml/LoggedNodeFactory.scala +++ /dev/null @@ -1,78 +0,0 @@ -package scala.xml; - -/** This class logs what the nodefactory is actually doing. -If you want to see what happens during loading, use it like this: -object testLogged with Application { - - val x = new scala.xml.nobinding.NoBindingFactoryAdapter - with scala.xml.LoggedNodeFactory[scala.xml.Elem]() - with scala.util.logging.ConsoleLogger; - - Console.println("Start"); - - val doc = x.loadXML(new org.xml.sax.InputSource("http://lamp.epfl.ch/~buraq")); - - Console.println("End"); - - Console.println(doc); -} - -*/ -abstract class LoggedNodeFactory[A <: Node] -extends NodeFactory[A] -with scala.util.logging.Logged { - - // configuration values; - val logNode = true; - val logText = false; - val logComment = false; - val logProcInstr = false; - - final val NONE = 0; - final val CACHE = 1; - final val FULL = 2; - /** 0 = no loggging, 1 = cache hits, 2 = detail */ - val logCompressLevel = 1; - - // methods of NodeFactory - - /** logged version of makeNode method */ - override def makeNode(pre:String, label:String, attrSeq:MetaData, scope: NamespaceBinding, children:Seq[Node]): A = { - if(logNode) - log("[makeNode for "+label+"]"); - - val hash = Utility.hashCode(pre, label, attrSeq.hashCode(), scope.hashCode(), children) ; - - /* - if(logCompressLevel >= FULL) { - log("[hashcode total:"+hash); - log(" elem name "+uname+" hash "+ ? )); - log(" attrs "+attrSeq+" hash "+attrSeq.hashCode()); - log(" children :"+children+" hash "+children.hashCode()); - } - */ - if(!cache.get( hash ).isEmpty && (logCompressLevel >= CACHE)) - log("[cache hit !]"); - - super.makeNode(pre, label, attrSeq, scope, children); - } - - override def makeText(s: String) = { - if(logText) - log("[makeText:\""+s+"\"]"); - super.makeText( s ); - } - - override def makeComment(s: String): Seq[Comment] = { - if(logComment) - log("[makeComment:\""+s+"\"]"); - super.makeComment( s ); - } - - override def makeProcInstr(t: String, s: String): Seq[ProcInstr] = { - if(logProcInstr) - log("[makeProcInstr:\""+t+" "+ s+"\"]"); - super.makeProcInstr(t,s); - } - -} diff --git a/sources/scala/xml/Node.scala b/sources/scala/xml/Node.scala index 7f73bc4260..58158eca9f 100644 --- a/sources/scala/xml/Node.scala +++ b/sources/scala/xml/Node.scala @@ -34,9 +34,6 @@ abstract class Node extends NodeSeq { /** label of this node. I.e. "foo" for <foo/>) */ def label: String; - /** the namespace of this node */ - //final def namespace: String = scope.getURI(prefix); - /** used internally. Text = -1 PI = -2 Comment = -3 EntityRef = -5 */ def typeTag$: Int = 0; @@ -76,17 +73,16 @@ abstract class Node extends NodeSeq { def descendant_or_self: List[Node] = this :: descendant; /** structural equality */ - override def equals(x: Any): Boolean = { - x match { + override def equals(x: Any): Boolean = x match { case that: Node => - (that.label == this.label ) + (that.prefix == this.prefix ) + &&(that.label == this.label ) &&(that.attributes == this.attributes) - && that.child.sameElements(this.child)// sameElements + && that.child.sameElements(this.child) // sameElements case _ => false - } } /** returns a hashcode */ - override def hashCode(): Int = 0; + override def hashCode(): Int; //Utility.hashCode(namespace, label, attributes.hashCode(), child); diff --git a/sources/scala/xml/NodeFactory.scala b/sources/scala/xml/NodeFactory.scala deleted file mode 100644 index c22ff2babd..0000000000 --- a/sources/scala/xml/NodeFactory.scala +++ /dev/null @@ -1,77 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -** $Id $ -\* */ - -package scala.xml; - -import scala.collection.Map ; -import scala.collection.mutable ; - -abstract class NodeFactory[A <: Node] { - - val ignoreComments = false; - val ignoreProcInstr = false; - - /* default behaviour is to use hash-consing */ - val cache = new mutable.HashMap[int,List[A]](); - - protected def create(pre: String, name: String, attrs: MetaData, scope: NamespaceBinding, children:Seq[Node]): A; - - protected def construct(hash:Int, old:List[A], pre: String, name: String, attrSeq:MetaData, scope: NamespaceBinding, children:Seq[Node]): A = { - val el = create(pre, name, attrSeq, scope, children); - cache.update( hash, el::old ); - el - } - - /** faster equality, because */ - def eqElements(ch1:Seq[Node], ch2:Seq[Node]): Boolean = { - (ch1.length == ch2.length) && { - val it1 = ch1.elements; - val it2 = ch2.elements; - var res = true; - while(res && it1.hasNext) { - res = it1.next.eq(it2.next); - } - res - } - } - - def nodeEquals(n: Node, pre: String, name: String, attrSeq:MetaData, scope: NamespaceBinding, children:Seq[Node]) = - (n.prefix == pre) - &&(n.label == name) - &&(n.attributes == attrSeq) - // scope?? - &&(eqElements(n.child,children)); - - def makeNode(pre: String, name: String, attrSeq:MetaData, scpe: NamespaceBinding, children:Seq[Node]): A = { - //Console.println("NodeFactory::makeNode("+pre+","+name+","+attrSeq+","+scpe+","+children+")"); - val hash = Utility.hashCode( pre, name, attrSeq.hashCode(), scpe.hashCode(), children ) ; - cache.get( hash ) match { - case Some(list) => // find structurally equal - val it = list.elements; - val lookup = it.find { x => nodeEquals(x, pre, name, attrSeq, scpe, children) }; - lookup match { - case Some(x) => - //Console.println("[cache hit !]"+x); - x; // return cached elem - case _ => construct(hash, list, pre, name, attrSeq, scpe, children); - } - case _ => construct(hash, Nil, pre, name, attrSeq, scpe, children) - } - } - - def makeText(s: String) = - Text( s ); - - def makeComment(s: String): Seq[Comment] = - if(ignoreComments) Nil else List(Comment( s )); - - def makeProcInstr(t: String, s: String): Seq[ProcInstr] = - if(ignoreProcInstr) Nil else List(ProcInstr(t, s)); - -} diff --git a/sources/scala/xml/ProcInstr.scala b/sources/scala/xml/ProcInstr.scala index 8b9669ab61..7a5ce461d6 100644 --- a/sources/scala/xml/ProcInstr.scala +++ b/sources/scala/xml/ProcInstr.scala @@ -18,6 +18,11 @@ package scala.xml; case class ProcInstr(target:String, text:String) extends SpecialNode { + if( !Parsing.isName( target ) ) + throw new IllegalArgumentException(target+" must be an XML Name"); + else if( text.indexOf("?>" ) != -1 ) + throw new IllegalArgumentException(text+" may not contain \"?>\""); + final override def typeTag$:Int = -2; val z:Seq[Char] = target; z match { @@ -25,14 +30,11 @@ case class ProcInstr(target:String, text:String) extends SpecialNode { throw new IllegalArgumentException(target+" is reserved"); case _ => } - if( !Parsing.isName( target ) ) - throw new IllegalArgumentException(target+" must be an XML Name"); - else if( text.indexOf("?>" ) != -1 ) - throw new IllegalArgumentException(text+" may not contain \"?>\""); - final override def equals(x:Any) = x match { - case x @ ProcInstr( t2, s2 ) => target.equals( t2 ) && text.equals( s2 ); - case _ => false; + /** structural equality */ + override def equals(x: Any): Boolean = x match { + case ProcInstr(x,y) => x.equals(target) && y.equals(text); + case _ => false } /** the constant "#PI" */ @@ -41,15 +43,18 @@ case class ProcInstr(target:String, text:String) extends SpecialNode { /** hashcode for this PI */ override def hashCode() = target.hashCode() * 7 + text.hashCode(); - /** returns "<?"+target+(" "+text)?+"?>" */ - final override def toString() = { - val sb = new StringBuffer("<?"); - sb.append(target); + /** appends "<?" target (" "+text)?+"?>" + * to this stringbuffer. + */ + def toString(sb: StringBuffer) = { + sb + .append("<?") + .append(target); if( text.length() > 0 ) { - sb.append(' '); - sb.append(text); + sb + .append(' ') + .append(text); }; sb.append("?>"); - sb.toString() } } diff --git a/sources/scala/xml/SpecialNode.scala b/sources/scala/xml/SpecialNode.scala index 9752400fd5..1162287e2f 100644 --- a/sources/scala/xml/SpecialNode.scala +++ b/sources/scala/xml/SpecialNode.scala @@ -14,13 +14,18 @@ package scala.xml; **/ abstract class SpecialNode extends Node { - /** always Node.EmptyNamespace */ - //final def namespace = Node.EmptyNamespace; - /** always empty */ - //final def attributes = Node.NoAttributes; + final override def attributes = Null; + + /** always Node.EmptyNamespace */ + final override def namespace = null; /** always empty */ final def child = Nil; + final override def toString(): String = + toString(new StringBuffer()).toString(); + + def toString(sb:StringBuffer): StringBuffer ; + } diff --git a/sources/scala/xml/Text.scala b/sources/scala/xml/Text.scala index 95fec1104f..b784ae5b58 100644 --- a/sources/scala/xml/Text.scala +++ b/sources/scala/xml/Text.scala @@ -9,23 +9,20 @@ package scala.xml; -import scala.collection.immutable ; /** an XML node for text (PCDATA). Used in both non-bound and bound XML * representations * @author Burak Emir * @param text the text contained in this node, may not be null. -**/ - - + */ case class Text[+A]( data: A ) extends SpecialNode { - /** @deprecated - */ - def text = toString(); - if(null == data) throw new java.lang.NullPointerException("tried to construct Text with null"); + /** @deprecated + */ + def text = data.toString(); + final override def typeTag$:Int = -1; /** the constant "#PCDATA" @@ -42,6 +39,7 @@ case class Text[+A]( data: A ) extends SpecialNode { override def hashCode() = data.hashCode(); /** returns text, with some characters escaped according to XML spec */ - override def toString() = Utility.escape( data.toString() ); + def toString(sb:StringBuffer) = + Utility.escape( data.toString(), sb ); } diff --git a/sources/scala/xml/Utility.scala b/sources/scala/xml/Utility.scala index 3dc9ee7b01..08ce7febce 100644 --- a/sources/scala/xml/Utility.scala +++ b/sources/scala/xml/Utility.scala @@ -9,10 +9,8 @@ package scala.xml; -import java.lang.StringBuffer; /* Java dependency! */ +import java.lang.StringBuffer; import scala.collection.mutable; -import scala.collection.immutable; -import scala.collection.Map; /** * Utility functions for processing instances of bound and not bound XML @@ -23,8 +21,12 @@ object Utility { def view(s: String): Text[String] = Text(s); /* escapes the characters < > & and " from string */ - def escape(text: String) = { - val s = new StringBuffer(); + final def escape(text: String): String = + escape(text, new StringBuffer()).toString(); + + + /* appends escaped string to s */ + final def escape(text: String, s: StringBuffer): StringBuffer = { for (val c <- Iterator.fromString(text)) c match { case '<' => s.append("<"); case '>' => s.append(">"); @@ -32,55 +34,37 @@ object Utility { case '"' => s.append("""); case _ => s.append(c); } - s.toString() + s } /** - * Returns a set of all namespaces appearing in a node and all its - * descendants, including the empty namespaces + * Returns a set of all namespaces used in a sequence of nodes + * and all their descendants, including the empty namespaces. * - * @param node - def collectNamespaces(node: Node): mutable.Set[String] = { - collectNamespaces(node, new mutable.HashSet[String]()); - } + * @param nodes */ - /** - * Returns a set of all namespaces appearing in a sequence of nodes - * and all their descendants, including the empty namespaces - * - * @param nodes def collectNamespaces(nodes: Seq[Node]): mutable.Set[String] = { var m = new mutable.HashSet[String](); - for (val n <- nodes) - collectNamespaces(n, m); + val it = nodes.elements; + while (it.hasNext) + collectNamespaces(it.next, m); m } - private def collectNamespaces(node: Node, set: mutable.Set[String]): mutable.Set[String] = { - def collect( n:Node ):Unit = { - if( n.typeTag$ >= 0 ) { - set += n.namespace; - for (val a <- n.attributes) - a.match { - case _:PrefixedAttribute => - set += a.getNamespace(n) - case _ => - } - for (val i <- n.child) - collect(i); - } + /** adds all namespaces in node to set */ + def collectNamespaces(n: Node, set: mutable.Set[String]): Unit = { + if( n.typeTag$ >= 0 ) { + set += n.namespace; + for (val a <- n.attributes) a.match { + case _:PrefixedAttribute => + set += a.getNamespace(n) + case _ => + } + for (val i <- n.child) + collectNamespaces(i, set); } - collect(node); - set } - */ - - /** - * A prefix mapping that maps the empty namespace to the empty prefix - */ - val noPrefixes: Map[String,String] = - immutable.ListMap.Empty[String,String].update("",""); /** string representation of an XML node, with comments stripped the comments * @see "toXML(Node, Boolean)" @@ -103,37 +87,26 @@ object Utility { } - /** serializes a tree to the given stringbuffer - * with the given namespace prefix mapping. - * elements and attributes that have namespaces not in pmap are <strong>ignored</strong> + /** appends a tree to the given stringbuffer within given namespace scope. + * * @param n the node * @param pscope the parent scope * @param sb stringbuffer to append to * @param stripComment if true, strip comments */ def toXML(x: Node, pscope: NamespaceBinding, sb: StringBuffer, stripComment: Boolean): Unit = { - //Console.println("inside toXML, x.label = "+x.label); - //Console.println("inside toXML, x.scope = "+x.scope); - //Console.println("inside toXML, pscope = "+pscope); x match { - case Text(t) => - sb.append(escape(t.toString())); - - case Comment(text) => - if (!stripComment) { - sb.append("<!--"); - sb.append(text); - sb.append("-->"); - } + case c: Comment if !stripComment => + c.toString(sb) - case _ if x.typeTag$ < 0 => - sb.append( x.toString() ); + case x: SpecialNode => + x.toString(sb) - case _ => { + case _ => // print tag with namespace declarations sb.append('<'); - x.nameToString(sb); //appendPrefixedName( x.prefix, x.label, pmap, sb ); + x.nameToString(sb); if (x.attributes != null) { x.attributes.toString(sb) } @@ -143,9 +116,9 @@ object Utility { toXML(c, x.scope, sb, stripComment); } sb.append("</"); - x.nameToString(sb); //appendPrefixedName(x.prefix, x.label, pmap, sb); + x.nameToString(sb); sb.append('>') - } + } } diff --git a/sources/scala/xml/nobinding/NoBindingFactoryAdapter.scala b/sources/scala/xml/nobinding/NoBindingFactoryAdapter.scala deleted file mode 100644 index 25563f8ecc..0000000000 --- a/sources/scala/xml/nobinding/NoBindingFactoryAdapter.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -** $Id$ -\* */ -package scala.xml.nobinding; - -import scala.collection.mutable; -import org.xml.sax.InputSource; - -/** nobinding adaptor providing callbacks to parser to create elements. -* implements hash-consing -*/ -class NoBindingFactoryAdapter extends FactoryAdapter with NodeFactory[Elem] { - - - // FactoryAdapter methods - - /** returns true. Every XML node may contain text that the application needs - **/ - def nodeContainsText( label:java.lang.String ):boolean = true; - - - // methods for NodeFactory[Elem] - protected def create(pre: String, label: String, attrs: MetaData, scpe: NamespaceBinding, children:Seq[Node]): Elem = { - Elem( pre, label, attrs, scpe, children:_* ); - } - - // methods for FactoryAdapter - - /** creates a node. never creates the same node twice, using hash-consing - */ - def createNode(pre:String, label: String, attrs: MetaData, scpe: NamespaceBinding, children: List[Node] ): Elem = { - //Console.println("NoBindingFactoryAdapter::createNode("+pre+","+label+","+attrs+","+scpe+","+children+")"); - Elem( pre, label, attrs, scpe, children:_* ); - - //makeNode(pre, label, attrs, scope, children); - } - - /** creates a text node - */ - def createText( text:String ) = - Text( text ); - - /** loads an XML document, returning a Symbol node. - */ - override def loadXML( source:InputSource ):Elem = - super.loadXML( source ).asInstanceOf[ Elem ]; - - def getDefaultNamespace(it:Iterator[Pair[String,String]]):String = { - while( it.hasNext ) { - val key = it.next; - if( key._1 == "xmlns") - return key._2 - } - return ""; - } - } diff --git a/sources/scala/xml/nobinding/XML.scala b/sources/scala/xml/nobinding/XML.scala deleted file mode 100644 index d762ccea39..0000000000 --- a/sources/scala/xml/nobinding/XML.scala +++ /dev/null @@ -1,76 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -** $Id$ -\* */ -package scala.xml.nobinding ; - -import org.xml.sax.InputSource; -import scala.collection.Map ; -import scala.collection.mutable.HashMap ; - -// import scala.xml.Utility ; - -/** functions to load and save XML elements. use this when data binding is not -** desired, i.e. when XML is handled using Symbol nodes -**/ -object XML { - - import java.io._ ; - - // functions for generic xml loading, saving - - /** loads XML from given file */ - def loadFile( file:File ):scala.xml.Elem = - new NoBindingFactoryAdapter().loadXML( new InputSource( - new FileInputStream( file ) - )); - - /** loads XML from given file descriptor */ - def loadFile( fileDesc:FileDescriptor ):scala.xml.Elem = - new NoBindingFactoryAdapter().loadXML( new InputSource( - new FileInputStream( fileDesc ) - )); - - /** loads XML from given file */ - def loadFile( fileName:String ):scala.xml.Elem = - new NoBindingFactoryAdapter().loadXML( new InputSource( - new FileInputStream( fileName ) - )); - - /** loads XML from given InputStream */ - def load( is:InputStream ):scala.xml.Elem = - new NoBindingFactoryAdapter().loadXML( new InputSource( is )); - - /** loads XML from given Reader */ - def load( reader:Reader ):scala.xml.Elem = - new NoBindingFactoryAdapter().loadXML( new InputSource( reader )); - - /** loads XML from given sysID */ - def load( sysID:String ):scala.xml.Elem = - new NoBindingFactoryAdapter().loadXML( new InputSource( sysID )); - - /** loads XML from a given input source*/ - def load( source:InputSource ):scala.xml.Elem = - new NoBindingFactoryAdapter().loadXML( source ); - - /** saves XML to filename with encoding ISO-8859-1 */ - def save( filename:String, doc:Elem ):Unit = { - /* using NIO classes of JDK 1.4 */ - import java.io.{FileOutputStream,Writer}; - import java.nio.channels.{Channels,FileChannel}; - - val fos = new FileOutputStream( filename ); - val w:Writer = Channels.newWriter( fos.getChannel(), "ISO-8859-1" ); - - /* 2do: optimize by giving writer parameter to toXML*/ - w.write( Utility.toXML( doc )); - - w.close(); - fos.close(); - } - -} diff --git a/test/files/jvm/xml01.scala b/test/files/jvm/xml01.scala index f97732a68e..3d2c7a2731 100644 --- a/test/files/jvm/xml01.scala +++ b/test/files/jvm/xml01.scala @@ -1,7 +1,6 @@ import java.io.StringReader; import org.xml.sax.InputSource; import scala.xml._; -import scala.xml.nobinding._; import scala.util.logging._; import scala.testing.UnitTest._ ; @@ -18,8 +17,9 @@ object Test with Application { val c = new Node { def label = "hello"; - //def namespace = ""; - def child = List(Elem("","world",e,sc)); + override def hashCode() = + Utility.hashCode(prefix, label, attributes.hashCode(), scope.hashCode(), child); + def child = Elem(null, "world", e, sc); //def attributes = e; }; @@ -36,10 +36,10 @@ object Test with Application { val i = new InputSource( new StringReader( x2 )); val x2p = XML.load( i ); - assertEquals(x2p, Elem("","book",e,sc, - Elem("","author",e,sc,Text("Peter Buneman")), - Elem("","author",e,sc,Text("Dan Suciu")), - Elem("","title",e,sc,Text("Data on ze web")))); + assertEquals(x2p, Elem(null,"book",e,sc, + Elem(null,"author",e,sc,Text("Peter Buneman")), + Elem(null,"author",e,sc,Text("Dan Suciu")), + Elem(null,"title",e,sc,Text("Data on ze web")))); val xmlFile2 = "<bib><book><author>Peter Buneman</author><author>Dan Suciu</author><title>Data on ze web</title></book><book><author>John Mitchell</author><title>Foundations of Programming Languages</title></book></bib>"; val isrc2 = new InputSource( new StringReader( xmlFile2 ) ); @@ -49,9 +49,9 @@ object Test with Application { Console.println("xpath \\"); - assertSameElements( parsedxml1 \ "_" , List( Elem("","world",e,sc) ) ); + assertSameElements( parsedxml1 \ "_" , List( Elem(null,"world",e,sc) ) ); - assertSameElements( parsedxml1 \ "world", List( Elem("","world",e,sc) ) ); + assertSameElements( parsedxml1 \ "world", List( Elem(null,"world",e,sc) ) ); /* Console.println( parsedxml2 \ "_" ); @@ -65,13 +65,13 @@ object Test with Application { parsedxml2 \ "_" , List( - Elem("","book", e,sc, - Elem("","author",e,sc,Text("Peter Buneman")), - Elem("","author",e,sc,Text("Dan Suciu")), - Elem("","title",e,sc,Text("Data on ze web"))), - Elem("","book",e,sc, - Elem("","author",e,sc,Text("John Mitchell")), - Elem("","title",e,sc,Text("Foundations of Programming Languages")))) + Elem(null,"book", e,sc, + Elem(null,"author",e,sc,Text("Peter Buneman")), + Elem(null,"author",e,sc,Text("Dan Suciu")), + Elem(null,"title",e,sc,Text("Data on ze web"))), + Elem(null,"book",e,sc, + Elem(null,"author",e,sc,Text("John Mitchell")), + Elem(null,"title",e,sc,Text("Foundations of Programming Languages")))) ); assertEquals( (parsedxml2 \ "author").length, 0 ); @@ -79,13 +79,13 @@ object Test with Application { parsedxml2 \ "book", List( - Elem("","book",e,sc, - Elem("","author",e,sc,Text("Peter Buneman")), - Elem("","author",e,sc,Text("Dan Suciu")), - Elem("","title",e,sc,Text("Data on ze web"))), - Elem("","book",e,sc, - Elem("","author",e,sc,Text("John Mitchell")), - Elem("","title",e,sc,Text("Foundations of Programming Languages"))) + Elem(null,"book",e,sc, + Elem(null,"author",e,sc,Text("Peter Buneman")), + Elem(null,"author",e,sc,Text("Dan Suciu")), + Elem(null,"title",e,sc,Text("Data on ze web"))), + Elem(null,"book",e,sc, + Elem(null,"author",e,sc,Text("John Mitchell")), + Elem(null,"title",e,sc,Text("Foundations of Programming Languages"))) ) ); @@ -94,11 +94,11 @@ object Test with Application { parsedxml2 \ "_" \ "_", List( - Elem("","author",e,sc,Text("Peter Buneman")), - Elem("","author",e,sc,Text("Dan Suciu")), - Elem("","title",e,sc,Text("Data on ze web")), - Elem("","author",e,sc,Text("John Mitchell")), - Elem("","title",e,sc,Text("Foundations of Programming Languages")) + Elem(null,"author",e,sc,Text("Peter Buneman")), + Elem(null,"author",e,sc,Text("Dan Suciu")), + Elem(null,"title",e,sc,Text("Data on ze web")), + Elem(null,"author",e,sc,Text("John Mitchell")), + Elem(null,"title",e,sc,Text("Foundations of Programming Languages")) ) ); @@ -107,9 +107,9 @@ object Test with Application { parsedxml2 \ "_" \ "author", List( - Elem("","author",e,sc,Text("Peter Buneman")), - Elem("","author",e,sc,Text("Dan Suciu")), - Elem("","author",e,sc,Text("John Mitchell")) + Elem(null,"author",e,sc,Text("Peter Buneman")), + Elem(null,"author",e,sc,Text("Dan Suciu")), + Elem(null,"author",e,sc,Text("John Mitchell")) ) ); @@ -123,9 +123,9 @@ object Test with Application { parsedxml2 \\ "author", List( - Elem("","author",e,sc,Text("Peter Buneman")), - Elem("","author",e,sc,Text("Dan Suciu")), - Elem("","author",e,sc,Text("John Mitchell")) + Elem(null,"author",e,sc,Text("Peter Buneman")), + Elem(null,"author",e,sc,Text("Dan Suciu")), + Elem(null,"author",e,sc,Text("John Mitchell")) ) ); @@ -134,30 +134,30 @@ object Test with Application { (new NodeSeq { val theSeq = List( parsedxml2 ) }) \\ "_", List( - Elem("","bib",e,sc, - Elem("","book",e,sc, - Elem("","author",e,sc,Text("Peter Buneman")), - Elem("","author",e,sc,Text("Dan Suciu")), - Elem("","title",e,sc,Text("Data on ze web"))), - Elem("","book",e,sc, - Elem("","author",e,sc,Text("John Mitchell")), - Elem("","title",e,sc,Text("Foundations of Programming Languages")))), - Elem("","book",e,sc, - Elem("","author",e,sc,Text("Peter Buneman")), - Elem("","author",e,sc,Text("Dan Suciu")), - Elem("","title",e,sc,Text("Data on ze web"))), - Elem("","author",e,sc,Text("Peter Buneman")), + Elem(null,"bib",e,sc, + Elem(null,"book",e,sc, + Elem(null,"author",e,sc,Text("Peter Buneman")), + Elem(null,"author",e,sc,Text("Dan Suciu")), + Elem(null,"title",e,sc,Text("Data on ze web"))), + Elem(null,"book",e,sc, + Elem(null,"author",e,sc,Text("John Mitchell")), + Elem(null,"title",e,sc,Text("Foundations of Programming Languages")))), + Elem(null,"book",e,sc, + Elem(null,"author",e,sc,Text("Peter Buneman")), + Elem(null,"author",e,sc,Text("Dan Suciu")), + Elem(null,"title",e,sc,Text("Data on ze web"))), + Elem(null,"author",e,sc,Text("Peter Buneman")), Text("Peter Buneman"), - Elem("","author",e,sc,Text("Dan Suciu")), + Elem(null,"author",e,sc,Text("Dan Suciu")), Text("Dan Suciu"), - Elem("","title",e,sc,Text("Data on ze web")), + Elem(null,"title",e,sc,Text("Data on ze web")), Text("Data on ze web"), - Elem("","book",e,sc, - Elem("","author",e,sc,Text("John Mitchell")), - Elem("","title",e,sc,Text("Foundations of Programming Languages"))), - Elem("","author",e,sc,Text("John Mitchell")), + Elem(null,"book",e,sc, + Elem(null,"author",e,sc,Text("John Mitchell")), + Elem(null,"title",e,sc,Text("Foundations of Programming Languages"))), + Elem(null,"author",e,sc,Text("John Mitchell")), Text("John Mitchell"), - Elem("","title",e,sc,Text("Foundations of Programming Languages")), + Elem(null,"title",e,sc,Text("Foundations of Programming Languages")), Text("Foundations of Programming Languages") ) ); @@ -168,7 +168,7 @@ object Test with Application { parsedxml2 \\ "title", List( - Elem("","title",e,sc,Text("Data on ze web")), - Elem("","title",e,sc,Text("Foundations of Programming Languages"))) + Elem(null,"title",e,sc,Text("Data on ze web")), + Elem(null,"title",e,sc,Text("Foundations of Programming Languages"))) ); } diff --git a/test/files/jvm/xmlstuff.scala b/test/files/jvm/xmlstuff.scala index 1418707f95..90ae82e18a 100644 --- a/test/files/jvm/xmlstuff.scala +++ b/test/files/jvm/xmlstuff.scala @@ -1,8 +1,7 @@ import java.io.StringReader; import org.xml.sax.InputSource; -import scala.xml.nobinding.XML; import scala.testing.UnitTest._ ; -import scala.xml.{Node,NodeSeq,Elem,Text}; +import scala.xml.{Node, NodeSeq, Elem, Text, XML}; object Test with Application { |