From d6963262b4a68577925b1281d246e30e3265e97a Mon Sep 17 00:00:00 2001 From: buraq Date: Mon, 9 Feb 2004 18:07:31 +0000 Subject: projections on XML ! preserving document order ! --- sources/scala/xml/Node.scala | 51 ++++++++++++++++++++++++++++++++++++++----- test/files/run/xmlstuff.check | 8 ++++++- test/files/run/xmlstuff.scala | 8 +++++++ 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/sources/scala/xml/Node.scala b/sources/scala/xml/Node.scala index b3200fdf7d..9e052d3648 100644 --- a/sources/scala/xml/Node.scala +++ b/sources/scala/xml/Node.scala @@ -21,6 +21,10 @@ trait Node { /** the string representation of this XML node */ def toXML: String; + /** 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): NodeList = new NodeList({ val iter = children.elements; if( "_" == that.label ) { @@ -34,15 +38,22 @@ trait Node { } }); + /** 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. + * The document order is preserved. + */ def /#(that:Symbol): NodeList = new NodeList({ var res:List[Node] = Nil; + var tmp:List[Node] = Nil; for( val x <- children.elements ) { - if ( x.label == that.label || "_" == that.label ) // order messed up here - res = x::res; - res =(x/#(that)).toList:::res; - + if ( x.label == that.label || "_" == that.label ) + tmp = x::tmp; + tmp = tmp:::(x/#(that)).toList; + res = res:::tmp; + tmp = Nil } - res.reverse + res; }); } @@ -51,6 +62,10 @@ trait Node { class NodeList(theList:List[Node]) extends List[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.label ) { new NodeList( res ) } else { @@ -58,6 +73,23 @@ class NodeList(theList:List[Node]) extends List[Node] { } + /** 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): NodeList = new NodeList( + if ( "_" == that.label ) { + this.flatMap ( x => (x/#'_).toList ) + } else { + this.flatMap ( x => { + if( x.label == that.label ) + x::(x/#(that)).toList; + else + (x/#(that)).toList; + }) + }); + + def toList:List[Node] = theList; // forwarding list methods @@ -65,10 +97,17 @@ class NodeList(theList:List[Node]) extends List[Node] { 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 ) ); - // == does not work + 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/test/files/run/xmlstuff.check b/test/files/run/xmlstuff.check index af85d96257..4636a6f8b4 100644 --- a/test/files/run/xmlstuff.check +++ b/test/files/run/xmlstuff.check @@ -20,4 +20,10 @@ parsedxml2/'_/'_/'author NodeList() parsedxml2/#'author -NodeList('author(Text(Dan Suciu)),'author(Text(Peter Buneman)),'author(Text(John Mitchell))) +NodeList('author(Text(Peter Buneman)),'author(Text(Dan Suciu)),'author(Text(John Mitchell))) + +new NodeList(List(parsedxml2))/#'_ +NodeList('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)),Text(Dan Suciu),'title(Text(Data on ze web)),Text(Data on ze web),'book('author(Text(John Mitchell)),'title(Text(Foundations of Programming Languages))),'author(Text(John Mitchell)),Text(John Mitchell),'title(Text(Foundations of Programming Languages)),Text(Foundations of Programming Languages)) + +new NodeList(List(parsedxml2))/#'title +NodeList('title(Text(Data on ze web)),'title(Text(Foundations of Programming Languages))) diff --git a/test/files/run/xmlstuff.scala b/test/files/run/xmlstuff.scala index 916798e112..28f753ce90 100644 --- a/test/files/run/xmlstuff.scala +++ b/test/files/run/xmlstuff.scala @@ -2,6 +2,7 @@ import java.io.StringReader; import org.xml.sax.InputSource; import scala.xml.nobinding.XML; import scala.testing.UnitTest.assertEquals ; +import scala.xml.NodeList; object Test with Application { val xmlFile1 = ""; @@ -39,4 +40,11 @@ object Test with Application { Console.println( "\nparsedxml2/#'author"); Console.println( parsedxml2/#'author ); + Console.println( "\nnew NodeList(List(parsedxml2))/#'_"); + Console.println( new NodeList( List( parsedxml2 ))/#'_ ); + + Console.println( "\nnew NodeList(List(parsedxml2))/#'title"); + Console.println( new NodeList( List( parsedxml2 ))/#'title ); + + } -- cgit v1.2.3