From 6c1888cb456c1fd87594399ca9cdeec4485dfaac Mon Sep 17 00:00:00 2001 From: buraq Date: Fri, 12 Mar 2004 20:08:43 +0000 Subject: changes to xml api --- sources/scala/tools/dtd2scala/DeclToScala.scala | 8 +- sources/scala/xml/Elem.scala | 53 ++++---- sources/scala/xml/Node.scala | 160 +++++++++++------------- sources/scala/xml/Text.scala | 15 +-- sources/scala/xml/Utility.scala | 8 +- 5 files changed, 113 insertions(+), 131 deletions(-) (limited to 'sources') diff --git a/sources/scala/tools/dtd2scala/DeclToScala.scala b/sources/scala/tools/dtd2scala/DeclToScala.scala index 95d3f94d71..4283fbba46 100644 --- a/sources/scala/tools/dtd2scala/DeclToScala.scala +++ b/sources/scala/tools/dtd2scala/DeclToScala.scala @@ -40,7 +40,7 @@ class DeclToScala(fOut:PrintWriter, case "template" => { lookup.update("objectName", objectName); lookup.update("compressDefault", compress.toString()); - n.children.elements.foreach { n => writeNode(n) } + n.child.elements.foreach { n => writeNode(n) } } case "elementBinding" => { for( val decl <- elemMap.values.elements ) { @@ -48,7 +48,7 @@ class DeclToScala(fOut:PrintWriter, lookup += "elementContainsText" -> decl.containsText.toString(); lookup += "elementContentModel" -> decl.contentModel; curAttribs = decl.attribs; - n.children.elements.foreach{ n => writeNode( n ) } + n.child.elements.foreach{ n => writeNode( n ) } } curAttribs = null; lookup -= "elementName"; @@ -58,7 +58,7 @@ class DeclToScala(fOut:PrintWriter, case "attributeAssign" => { for( val aDecl <- curAttribs.keys.elements ) { lookup += "attributeName" -> aDecl; - n.children.elements.foreach{ n => writeNode( n ) } + n.child.elements.foreach{ n => writeNode( n ) } } lookup -= "attributeName"; } @@ -66,7 +66,7 @@ class DeclToScala(fOut:PrintWriter, case "attributeBinding" => { for( val aDecl <- curAttribs.keys.elements ) { lookup += "attributeName" -> aDecl; - n.children.elements.foreach{ n => writeNode( n ) } + n.child.elements.foreach{ n => writeNode( n ) } } lookup -= "attributeName"; } diff --git a/sources/scala/xml/Elem.scala b/sources/scala/xml/Elem.scala index 950a85f49f..bd4aabb054 100644 --- a/sources/scala/xml/Elem.scala +++ b/sources/scala/xml/Elem.scala @@ -1,39 +1,42 @@ package scala.xml ; -import scala.collection.immutable.{Map,ListMap} ; +import scala.collection.mutable.HashMap ; -case class Elem( name:String, children:Node* ) extends AttributedNode { +case class Elem( label:String, child:Node* ) extends Node with Similarity { - /** Returns the symbol name as a string. - */ - def label:String = name; + def similar( x:Any ) = { + x match { + case that:Node => (label == that.label) && child.similar( that.child ) + case _ => false; + } + } - /** Returns the list of children of this symbol. - def children: NodeSeq = new NodeSeq( List.fromIterator( - elems.elements map ( x => x match { - case n:Node => n; - case _ => Text(x.toString()); - }))); - */ + private val hmap = new HashMap[String,String](); - /** Returns a map representing the attributes of this node. + /** the attributes axis - default is Nil */ - def attributes: Map[String, String] = ListMap.Empty; + def attribute: Seq[Pair[String, String]] = hmap.elements.toSeq( hmap.size ); - /** returns a new symbol with updated attributes + /** returns a new element with updated attributes */ - final def %(attrs: List[Pair[String, String]]) = - new Elem( name, children:_* ) { - val themap = Elem.this.attributes.incl( attrs ); - override def attributes = themap; + final def %(attrs: Seq[Pair[String, String]]) = { + val newmap = new HashMap[String,String](); + for( val p <- hmap.elements ) { newmap += p._1 -> p._2 }; + for( val p <- attrs ) { newmap += p._1 -> p._2 }; + new Elem( label, child:_* ) { + private val hmap = newmap; + //override def attribute = newmap.elements.toSeq( newmap.size ); }; - + } /** returns a new symbol with updated attribute */ - final def %(attr: Pair[String, String]) = - new Elem( name, children:_* ) { - val themap = Elem.this.attributes.incl( attr ); - override def attributes = themap; + final def %(attr: Pair[String, String]) = { + val newmap = new HashMap[String,String](); + for( val p <- hmap.elements ) { newmap += p._1 -> p._2 }; + newmap += attr._1 -> attr._2; + new Elem( label, child:_* ) { + private val hmap = newmap; + //override def attribute = newmap.elements.toSeq( newmap.size ); }; - + } } diff --git a/sources/scala/xml/Node.scala b/sources/scala/xml/Node.scala index f050b35dc1..00c5d88549 100644 --- a/sources/scala/xml/Node.scala +++ b/sources/scala/xml/Node.scala @@ -9,108 +9,90 @@ package scala.xml ; +import scala.collection.mutable.AppendBuffer ; -/** Trait for representation of XML elements. These are created by - * a dtd2scala binding tool +/** Trait for representing XML using nodes of a labelled tree. + * This trait contains an implementation of a subset of XPath for navigation. */ trait Node { - /** the label of this XML node */ - def label: String; - /** the children of this XML node */ - def children: Seq[Node]; - /** the string representation of this XML node */ - def toXML: String; - /** projection function. Similar to XPath, use this./'foo to get a list + /** QName (the label of this node). I.e. "foo" for <foo/>) */ + def label: String; + + /** attribute axis */ + def attribute: Seq[ Pair[String,String] ]; + + final def apply(key: String): Option[String] = { + val it = attribute.elements.filter { x => key == x._1 }; + if( it.hasNext ) Some( it.next._2 ) else None + } + + /** child axis (all children of this node) */ + def child: Seq[Node]; + + /** descendant axis (all descendants of this node) */ + def descendant:Seq[Node] = child.toList.flatMap { + x => x::x.descendant.asInstanceOf[List[Node]] + } ; + + /** descendant axis (all descendants of this node) */ + def descendant_or_self:Seq[Node] = this::child.toList.flatMap { + x => x::x.descendant.asInstanceOf[List[Node]] + } ; + + override def equals( x:Any ):boolean = x match { + case that:Node => + //Console.print("(Node)"); + that.label == this.label && + that.attribute.similar( this.attribute ) && + that.child.similar( this.child ) + 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:Symbol): NodeSeq = new NodeSeq({ - val iter = children.elements; - if( "_" == that.name ) { - List.fromIterator( iter ); - } else { - var res:List[Node] = Nil; - for( val x <- iter; x.label == that.name ) { - res = x::res; - } - res.reverse + def \(that:Symbol): NodeSeq = { + new NodeSeq({ + val iter = child.elements; + that.name match { + + case "_" => iter.toList; + case _ => + var res:List[Node] = Nil; + for( val x <- child.elements; x.label == that.name ) { + res = x::res; + } + res.reverse } }); + } - /** projection function. Similar to XPath, use this./#'foo to get a list - * of all descendants of this node that are labelled with "foo". - * Use /'_ as a wildcard. + /** 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:Symbol): NodeSeq = new NodeSeq({ - var res:List[Node] = Nil; - var tmp:List[Node] = Nil; - for( val x <- children.elements ) { - if ( x.label == that.name || "_" == that.name ) - tmp = x::tmp; - tmp = tmp:::(x||(that)).toList; - res = res:::tmp; - tmp = Nil - } - res; - }); - -} - -/* a wrapper that adds a filter method */ -class NodeSeq(theList:List[Node]) extends Seq[Node] { - val res = theList.flatMap ( x => List.fromIterator( x.children.elements )); - - /** projection function. Similar to XPath, use this./'foo to get a list - * of all elements of this sequence that are labelled with "foo". - * Use /'_ as a wildcard. The document order is preserved. - */ - def |(that: Symbol) = if( "_" == that.name ) { - new NodeSeq( res ) - } else { - new NodeSeq( res.filter( y => y.label == that.name )) + def \\(that:Symbol): NodeSeq = { + new NodeSeq( + that.name match { + case "_" => this.descendant_or_self; + case _ => this.descendant_or_self.asInstanceOf[List[Node]]. + filter( x => x.label == that.name ); + /* + val res = new AppendBuffer[Node](); + if( this.label == that.name ) + res.append( this ); + res.append( this.child.elements.flatMap { + x => //x.\\(that).elements + }.toSeq); + res.toList + */ + }) } + override def hashCode() = Utility.hashCode(label, attribute.toList.hashCode(), child); + /** string representation of this node */ + override def toString() = Utility.toXML(this); - /** projection function. Similar to XPath, use this./'foo to get a list - * of all children of this node that are labelled with "foo" - * Use ||'_ as a wildcard. The document order is preserved. - */ - def ||(that: Symbol): NodeSeq = new NodeSeq( - if ( "_" == that.name ) { - theList.flatMap ( x => (x||'_).toList ) - } else { - theList.flatMap ( x => { - if( x.label == that.name ) - x::(x||(that)).toList; - else - (x||(that)).toList; - }) - }); - - override def toList:List[Node] = theList; - - /* Seq methods */ - def length = theList.length; - def elements = theList.elements ; - def apply( i:int ) = theList.apply( i ); - /* forwarding list methods - def isEmpty: boolean = theList.isEmpty; - def head: Node = theList.head; - def tail: List[Node] = theList.tail; - - override def toString():String = "Node"+theList.toString(); - - override def filter(p: Node => Boolean): NodeList = - new NodeList( theList.filter( p ) ); - - override def foreach(f: Node => Unit): Unit = theList.foreach( f ); - - override def flatMap[b](f: Node => List[b]): List[b] = theList.flatMap( f ); - - override def :::[b >: Node](prefix: List[b]): List[b] = theList.:::( prefix ); - */ - - //the == method cannot be forwarded :-( } diff --git a/sources/scala/xml/Text.scala b/sources/scala/xml/Text.scala index bb1ec0354c..1c5ab0ddb2 100644 --- a/sources/scala/xml/Text.scala +++ b/sources/scala/xml/Text.scala @@ -12,6 +12,7 @@ package scala.xml; import scala.collection.Map ; /** 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 **/ @@ -21,19 +22,15 @@ case class Text( text:String ) extends Node { */ def label = "#PCDATA"; - /** always returns an empty list - */ - final def children = Nil; + /** always empty */ + final def attribute = Nil; + /** always empty */ + final def child = Nil; override def hashCode() = text.hashCode(); - /** returns "Text("+raw text+")" - */ + /** returns text, with some characters escaped according to XML spec */ override def toString() = Utility.escape( text ); - /** returns PCDATA text, with some characters escaped according to XML spec - */ - override def toXML = Utility.escape( text ); - } diff --git a/sources/scala/xml/Utility.scala b/sources/scala/xml/Utility.scala index fd9eda8e5d..818df1b0b6 100644 --- a/sources/scala/xml/Utility.scala +++ b/sources/scala/xml/Utility.scala @@ -37,15 +37,15 @@ object Utility { def toXML( n:Node ):String = n match { case Text( t ) => escape( t ); - case x:AttributedNode => { + case x:Node => { val s = new StringBuffer(); s.append('<'); s.append( x.label ); - if( null != x.attributes ) { - s.append( attr2xml( x.attributes.elements ) );{} + if( x.attribute.length != 0 ) { + s.append( attr2xml( x.attribute.elements ) );{} } s.append('>'); - s.append( toXML( x.children.elements ) ); + s.append( toXML( x.child.elements ) ); s.append("'); -- cgit v1.2.3