summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sources/scala/tools/dtd2scala/DeclToScala.scala8
-rw-r--r--sources/scala/xml/Elem.scala53
-rw-r--r--sources/scala/xml/Node.scala160
-rw-r--r--sources/scala/xml/Text.scala15
-rw-r--r--sources/scala/xml/Utility.scala8
-rw-r--r--test/files/jvm/xmlstuff.check10
-rw-r--r--test/files/jvm/xmlstuff.scala140
7 files changed, 207 insertions, 187 deletions
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 &lt;foo/&gt;) */
+ 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("</");
s.append( x.label );
s.append('>');
diff --git a/test/files/jvm/xmlstuff.check b/test/files/jvm/xmlstuff.check
index fafc444191..8fb144e796 100644
--- a/test/files/jvm/xmlstuff.check
+++ b/test/files/jvm/xmlstuff.check
@@ -1,11 +1,21 @@
+equality
passed ok
passed ok
passed ok
passed ok
passed ok
+xpath \
passed ok
passed ok
passed ok
passed ok
passed ok
passed ok
+case _
+passed ok
+case _
+passed ok
+xpath \\
+passed ok
+passed ok
+passed ok
diff --git a/test/files/jvm/xmlstuff.scala b/test/files/jvm/xmlstuff.scala
index db6e3f90a0..ebd140d301 100644
--- a/test/files/jvm/xmlstuff.scala
+++ b/test/files/jvm/xmlstuff.scala
@@ -2,70 +2,93 @@ import java.io.StringReader;
import org.xml.sax.InputSource;
import scala.xml.nobinding.XML;
import scala.testing.UnitTest._ ;
-import scala.xml.{Node,NodeSeq};
+import scala.xml.{Node,NodeSeq,Text};
object Test with Application {
-
- def eq( a:Seq[Node], b:Seq[Node] ) = {
- if( a.length == b.length ) {
- val ita = a.elements;
- val itb = b.elements;
- var res = true;
- while( ita.hasNext ) {
- res = res &&( ita.next == itb.next );
- };
- res
- } else {
- false
- }
+/*
+ def eq( a:Seq[Node], b:Seq[Node] ):boolean = {
+ (a.length == b.length) && eq(a.elements,b.elements)
+ }
+ def eq( ita:Iterator[Node], itb:Iterator[Node] ) = {
+ var res = true;
+ while( ita.hasNext && itb.hasNext && res ) {
+ res = (ita.next == itb.next);
+ };
+ !ita.hasNext && !itb.hasNext && res
}
+ */
val xmlFile1 = "<hello><world/></hello>";
val isrc1 = new InputSource( new StringReader( xmlFile1 ) );
val parsedxml1 = XML.load( isrc1 );
+ val isrc11 = new InputSource( new StringReader( xmlFile1 ) );
+ val parsedxml11 = XML.load( isrc11 );
+
+ val c = new Node {
+ def label = "hello";
+ def child = List('world());
+ def attribute = List();
+ };
+
+ Console.println("equality");
+ assertEquals( c, parsedxml11 );
+ assertEquals( parsedxml1, parsedxml11 );
+ assertSimilar( List(parsedxml1), List(parsedxml11));
+ assertSimilar( Iterator.fromArray(Predef.Array(parsedxml1)).toSeq(1), List(parsedxml11));
+
+ val x2 = "<book><author>Peter Buneman</author><author>Dan Suciu</author><title>Data on ze web</title></book>";
+
+ val i = new InputSource( new StringReader( x2 ));
+ val x2p = XML.load( i );
+
+ assertSimilar(x2p, 'book('author(Text("Peter Buneman")),
+ 'author(Text("Dan Suciu")),
+ 'title(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 ) );
val parsedxml2 = XML.load( isrc2 );
// xmlFile2/book -> book,book
+ Console.println("xpath \\");
- assertEquals( eq( parsedxml1/'_ ,List('world()) ), true);
- assertEquals( eq( parsedxml1/'world ,List('world()) ), true);
- assertEquals(
- eq(
+ assertSimilar( parsedxml1 \ '_ , List( 'world() ) );
- parsedxml2/'_,
+ assertSimilar( parsedxml1 \ 'world, List( 'world() ) );
+
+/*
+ Console.println( parsedxml2 \ '_ );
+ Console.println( (parsedxml2 \ '_).elements);
+ for( val i <- (parsedxml2 \ '_).elements) {
+ Console.println( i );
+ };
+ */
+ assertSimilar(
+ parsedxml2 \ '_ ,
List(
'book('author(Text("Peter Buneman")),
'author(Text("Dan Suciu")),
'title(Text("Data on ze web"))),
'book('author(Text("John Mitchell")),
- 'title(Text("Foundations of Programming Languages")))
- )), true );
-
+ 'title(Text("Foundations of Programming Languages"))))
+ );
+ assertEquals( (parsedxml2 \ 'author).length, 0 );
- assertEquals( (parsedxml2/'author).length == 0, true );
-
-
- assertEquals(
- eq(
-
- parsedxml2/'book,
+ assertSimilar(
+ parsedxml2 \ 'book,
List(
'book('author(Text("Peter Buneman")),
'author(Text("Dan Suciu")),
'title(Text("Data on ze web"))),
'book('author(Text("John Mitchell")),
- 'title(Text("Foundations of Programming Languages")))
- )), true );
+ 'title(Text("Foundations of Programming Languages"))))
+ );
- assertEquals(
- eq(
+ assertSimilar(
- parsedxml2/'_/'_,
+ parsedxml2 \ '_ \ '_,
List('author(Text("Peter Buneman")),
'author(Text("Dan Suciu")),
@@ -73,41 +96,48 @@ object Test with Application {
'author(Text("John Mitchell")),
'title(Text("Foundations of Programming Languages")))
- ), true);
+ );
- assertEquals(
- eq(
+ assertSimilar(
- parsedxml2/'_/'author,
+ parsedxml2 \ '_ \ 'author,
List('author(Text("Peter Buneman")),
'author(Text("Dan Suciu")),
'author(Text("John Mitchell")))
- ), true);
+ );
+
+ assertSimilar( (parsedxml2 \ '_ \ '_ \ 'author), List() );
- assertEquals( (parsedxml2/'_/'_/'author).length == 0, true );
+ Console.println("xpath \\\\");
- assertEquals(
- eq(
+ assertSimilar(
- parsedxml2/#'author,
+ parsedxml2 \\ 'author,
List('author(Text("Peter Buneman")),
'author(Text("Dan Suciu")),
'author(Text("John Mitchell")))
- ), true );
+ );
- assertEquals(
- eq(
+ assertSimilar(
- parsedxml2/#'_,
+ new NodeSeq(List( parsedxml2 ))\\ '_,
List(
- 'book('author(Text("Peter Buneman")),
- 'author(Text("Dan Suciu")),
- 'title(Text("Data on ze web"))),
+ 'bib(
+ 'book(
+ 'author(Text("Peter Buneman")),
+ 'author(Text("Dan Suciu")),
+ 'title(Text("Data on ze web"))),
+ 'book('author(Text("John Mitchell")),
+ 'title(Text("Foundations of Programming Languages")))),
+ 'book(
+ 'author(Text("Peter Buneman")),
+ 'author(Text("Dan Suciu")),
+ 'title(Text("Data on ze web"))),
'author(Text("Peter Buneman")),
Text("Peter Buneman"),
'author(Text("Dan Suciu")),
@@ -120,17 +150,15 @@ object Test with Application {
Text("John Mitchell"),
'title(Text("Foundations of Programming Languages")),
Text("Foundations of Programming Languages"))
- ) , true);
+ );
- assertEquals(
- eq(
+ assertSimilar(
- parsedxml2/#'title,
+ parsedxml2 \\ 'title,
List(
'title(Text("Data on ze web")),
'title(Text("Foundations of Programming Languages")))
- ) , true);
-
+);
}