diff options
author | Burak Emir <emir@epfl.ch> | 2006-09-03 21:27:08 +0000 |
---|---|---|
committer | Burak Emir <emir@epfl.ch> | 2006-09-03 21:27:08 +0000 |
commit | f81fd55cf6e27290a2ab6f03f98f07aceacd2ba6 (patch) | |
tree | f85425677a69f83f123eda2791cee3761c781d33 | |
parent | 9ea0d2b4bcc7a5550a94c522402adb90ab3f0e18 (diff) | |
download | scala-f81fd55cf6e27290a2ab6f03f98f07aceacd2ba6.tar.gz scala-f81fd55cf6e27290a2ab6f03f98f07aceacd2ba6.tar.bz2 scala-f81fd55cf6e27290a2ab6f03f98f07aceacd2ba6.zip |
added group and changed metadata
-rw-r--r-- | src/library/scala/xml/Group.scala | 57 | ||||
-rw-r--r-- | src/library/scala/xml/MetaData.scala | 51 | ||||
-rw-r--r-- | src/library/scala/xml/Node.scala | 7 | ||||
-rw-r--r-- | src/library/scala/xml/NodeSeq.scala | 9 | ||||
-rw-r--r-- | src/library/scala/xml/Null.scala | 50 | ||||
-rw-r--r-- | src/library/scala/xml/PrefixedAttribute.scala | 8 | ||||
-rw-r--r-- | src/library/scala/xml/UnprefixedAttribute.scala | 10 | ||||
-rw-r--r-- | src/library/scala/xml/Utility.scala | 7 | ||||
-rw-r--r-- | src/library/scala/xml/parsing/MarkupParser.scala | 10 | ||||
-rw-r--r-- | test/files/jvm/xml01.check | 3 | ||||
-rw-r--r-- | test/files/jvm/xml01.scala | 9 | ||||
-rw-r--r-- | test/files/jvm/xmlstuff.scala | 11 |
12 files changed, 147 insertions, 85 deletions
diff --git a/src/library/scala/xml/Group.scala b/src/library/scala/xml/Group.scala new file mode 100644 index 0000000000..7fae60725b --- /dev/null +++ b/src/library/scala/xml/Group.scala @@ -0,0 +1,57 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml; + +import scala.runtime.compat.StringBuilder; + +/** a hack to group XML nodes in one node for output + * @author Burak Emir + */ +[serializable] +case class Group(val nodes:Seq[Node]) extends Node { + + override def theSeq = nodes + + /** structural equality */ + override def equals(x: Any) = x match { + case z:Node => (length == 1) && z == apply(0) + case z:Seq[Node] => sameElements( z ) + case z:String => text == z + case _ => false; + } + + /** always null */ + final def label = error("class Group does not support method 'label'") + + /** always empty */ + final override def attributes = error("class Group does not support method 'attributes'") + + + /** always null */ + final override def namespace = error("class Group does not support method 'namespace'") + + /** always empty */ + final override def child = error("class Group does not support method 'child'") + + /** returns text, with some characters escaped according to XML spec */ + def toString(sb: StringBuilder) = + error("class Group does not support method toString(StringBuilder)") + + override def text = { // same impl as NodeSeq + val sb = new StringBuilder(); + val it = elements; + while(it.hasNext) { + sb.append(it.next.text); + } + sb.toString(); + } +} diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala index 33e8fe2e88..f9d7b51c31 100644 --- a/src/library/scala/xml/MetaData.scala +++ b/src/library/scala/xml/MetaData.scala @@ -29,9 +29,13 @@ abstract class MetaData extends Iterable[MetaData] { def append(m: MetaData): MetaData = next.append(copy(m)) - def apply(s:String) = getValue(s) + def apply(s:String): Seq[Node] - def apply(uri:String, scp:NamespaceBinding, k:String)= getValue(uri, scp, k) + /** convenience method, same as apply(namespace, owner.scope, key) */ + final def apply(namespace: String, owner: Node, key: String): Seq[Node] = + apply(namespace, owner.scope, key) + + def apply(uri:String, scp:NamespaceBinding, k:String): Seq[Node] def containedIn1(m: MetaData): Boolean = m.equals1(this) || containedIn1(m.next) @@ -80,31 +84,6 @@ abstract class MetaData extends Iterable[MetaData] { } } - /* returns a sequences of "pseudo nodes" that contain attribute info. - not sure if this useful, and it violates contract for nodes... - def nodes = { - class NodeProxy(last:MetaData) extends Node { - override def prefix = last match { - case p:PrefixedAttribute => p.pre - case _ => null - } - override def label = "@"+last.key - override def child = Text(last.value) - override def text = last.value - } - val ns = new Array[Node](this.length) - var i = 0 - val it = elements - while(it.hasNext) { - val a = it.next - ns(i) = new NodeProxy(a) - i = i + 1 - } - val seq = array2seq(ns) - NodeSeq.fromSeq(seq) - } - */ - /** shallow equals method */ def equals1(that: MetaData): Boolean @@ -126,14 +105,22 @@ abstract class MetaData extends Iterable[MetaData] { def next: MetaData /** gets value of unqualified (unprefixed) attribute with given key */ - def getValue(key: String): Seq[Node] + final def get(key: String): Option[Seq[Node]] = apply(key) match { + case null => None + case x => Some(x) + } - /** gets value of qualified (prefixed) attribute with given key */ - def getValue(namespace: String, owner: Node, key: String): Seq[Node] = - getValue(namespace, owner.scope, key) + /** same as get(namespace, owner.scope, key) */ + final def get(namespace: String, owner: Node, key: String): Option[Seq[Node]] = + get(namespace, owner.scope, key) /** gets value of qualified (prefixed) attribute with given key */ - def getValue(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] + final def get(namespace: String, scope: NamespaceBinding, key: String): Option[Seq[Node]] = + apply(namespace, scope, key) match { + case null => None + case x => Some(x) + } + override def hashCode(): Int def toString1(): String = { diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala index 0ce3784a8b..db0157970e 100644 --- a/src/library/scala/xml/Node.scala +++ b/src/library/scala/xml/Node.scala @@ -70,7 +70,7 @@ abstract class Node extends NodeSeq { * @return value of <code>UnprefixedAttribute</code> with given key * in attributes, if it exists, otherwise <code>null</code>. */ - final def attribute(key: String) = attributes.getValue(key); + final def attribute(key: String) = attributes.get(key); /** * Convenience method, looks up a prefixed attribute in attributes of this node. @@ -81,7 +81,7 @@ abstract class Node extends NodeSeq { * @return value of <code>PrefixedAttribute</code> with given namespace * and given key, otherwise <code>null</code>. */ - final def attribute(uri: String, key: String) = attributes.getValue(uri, this, key); + final def attribute(uri: String, key: String) = attributes.get(uri, this, key); /** * Returns attribute meaning all attributes of this node, prefixed and unprefixed, @@ -115,6 +115,7 @@ abstract class Node extends NodeSeq { * attributes and children */ override def equals(x: Any): Boolean = x match { + case g:Group => false case that: Node => ((that.prefix == this.prefix ) &&(that.label == this.label ) @@ -134,7 +135,7 @@ abstract class Node extends NodeSeq { /** * returns a sequence consisting of only this node */ - final def theSeq = this :: Nil; + def theSeq:Seq[Node] = this :: Nil; /** * String representation of this node diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala index ee18c5bceb..93b6197b32 100644 --- a/src/library/scala/xml/NodeSeq.scala +++ b/src/library/scala/xml/NodeSeq.scala @@ -61,11 +61,10 @@ abstract class NodeSeq extends Seq[Node] { case _ if (that.charAt(0) == '@') && (this.length == 1) => val k = that.substring(1); val y = this(0); - val v = y.attribute(k); - if( v != null ) { - v // NodeSeq.fromSeq(Seq.single(Text(v):Node)); - } else - NodeSeq.Empty + y.attribute(k) match { + case Some(x) => Group(x) + case _ => NodeSeq.Empty + } case _ => var zs:List[Node] = Nil diff --git a/src/library/scala/xml/Null.scala b/src/library/scala/xml/Null.scala index 1a78c773b0..8f207d5349 100644 --- a/src/library/scala/xml/Null.scala +++ b/src/library/scala/xml/Null.scala @@ -9,70 +9,68 @@ // $Id$ -package scala.xml; +package scala.xml import scala.runtime.compat.StringBuilder case object Null extends MetaData { /** appends given MetaData items to this MetaData list */ - override def append(m: MetaData): MetaData = m; + override def append(m: MetaData): MetaData = m - override def containedIn1(m: MetaData): Boolean = false; + override def containedIn1(m: MetaData): Boolean = false /** returns its argument */ - def copy(next: MetaData) = next; + def copy(next: MetaData) = next + override def elements = Iterator.empty[MetaData] - override def elements = Iterator.empty[MetaData]; - - override def filter(f: MetaData => Boolean): MetaData = this; + override def filter(f: MetaData => Boolean): MetaData = this /** returns null */ - def getNamespace(owner: Node) = null; + def getNamespace(owner: Node) = null - final override def hasNext = false; + final override def hasNext = false - final override def length = 0; + final override def length = 0 - final override def length(i: Int) = i; + final override def length(i: Int) = i - def isPrefixed = false; + def isPrefixed = false /** deep equals method */ override def equals(that: Any) = that match { case m: MetaData => m.length == 0 - case _ => false; + case _ => false } - def equals1(that:MetaData) = that.length == 0; + def equals1(that:MetaData) = that.length == 0 - def key = null; + def key = null - def value = null; + def value = null - override def map(f: MetaData => Text): List[Text] = Nil; + override def map(f: MetaData => Text): List[Text] = Nil - def next = null; + def next = null /** null */ - def getValue(key: String) = null; + def apply(key: String) = null /** gets value of qualified (prefixed) attribute with given key */ - def getValue(namespace: String, scope: NamespaceBinding, key: String) = - null; + def apply(namespace: String, scope: NamespaceBinding, key: String) = null - override def hashCode(): Int = 0; + override def hashCode(): Int = 0 - override def toString1(): String = ""; + override def toString1(): String = "" //appends string representations of single attribute to StringBuilder - def toString1(sb:StringBuilder) = {}; + def toString1(sb:StringBuilder) = {} - override def toString(): String = ""; + override def toString(): String = "" override def toString(sb: StringBuilder): Unit = {} - override def wellformed(scope: NamespaceBinding) = true; + override def wellformed(scope: NamespaceBinding) = true } diff --git a/src/library/scala/xml/PrefixedAttribute.scala b/src/library/scala/xml/PrefixedAttribute.scala index cb8dbb0082..e4c4f50fec 100644 --- a/src/library/scala/xml/PrefixedAttribute.scala +++ b/src/library/scala/xml/PrefixedAttribute.scala @@ -60,15 +60,15 @@ class PrefixedAttribute(val pre: String, owner.getNamespace(pre) /** forwards the call to next (because caller looks for unprefixed attribute */ - def getValue(key: String): Seq[Node] = next.getValue(key) + def apply(key: String): Seq[Node] = next(key) /** gets attribute value of qualified (prefixed) attribute with given key */ - def getValue(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] = { + def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] = { if (key == this.key && scope.getURI(pre) == namespace) value else - next.getValue(namespace, scope, key) + next(namespace, scope, key) } /** returns true */ @@ -91,7 +91,7 @@ class PrefixedAttribute(val pre: String, } def wellformed(scope: NamespaceBinding): Boolean = { - (null == next.getValue(scope.getURI(pre), scope, key) && + (null == next(scope.getURI(pre), scope, key) && next.wellformed(scope)) } diff --git a/src/library/scala/xml/UnprefixedAttribute.scala b/src/library/scala/xml/UnprefixedAttribute.scala index 77c43c783d..02adb75219 100644 --- a/src/library/scala/xml/UnprefixedAttribute.scala +++ b/src/library/scala/xml/UnprefixedAttribute.scala @@ -45,8 +45,8 @@ class UnprefixedAttribute(val key: String, val value: Seq[Node], val next: MetaD * @param key * @return .. */ - def getValue(key: String): Seq[Node] = - if (key == this.key) value else next.getValue(key) + def apply(key: String): Seq[Node] = + if (key == this.key) value else next(key) /** * Forwards the call to next (because caller looks for prefixed attribute). @@ -56,8 +56,8 @@ class UnprefixedAttribute(val key: String, val value: Seq[Node], val next: MetaD * @param key * @return .. */ - def getValue(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] = - next.getValue(namespace, scope, key) + def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] = + next(namespace, scope, key) override def hashCode() = key.hashCode() * 7 + value.hashCode() * 53 + next.hashCode() @@ -76,7 +76,7 @@ class UnprefixedAttribute(val key: String, val value: Seq[Node], val next: MetaD } def wellformed(scope: NamespaceBinding): Boolean = - (null == next.getValue(null, scope, key)) && next.wellformed(scope) + (null == next(null, scope, key)) && next.wellformed(scope) } diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index 91e4516b1c..dd3afc61a0 100644 --- a/src/library/scala/xml/Utility.scala +++ b/src/library/scala/xml/Utility.scala @@ -104,6 +104,11 @@ object Utility extends AnyRef with parsing.TokenTests { case x: SpecialNode => x.toString(sb) + case g: Group => + for (val c <- g.nodes) { + toXML(c, x.scope, sb, stripComment) + } + case _ => // print tag with namespace declarations sb.append('<') @@ -113,7 +118,7 @@ object Utility extends AnyRef with parsing.TokenTests { } x.scope.toString(sb, pscope) sb.append('>') - for (val c <- x.child.elements) { + for (val c <- x.child) { toXML(c, x.scope, sb, stripComment) } sb.append("</") diff --git a/src/library/scala/xml/parsing/MarkupParser.scala b/src/library/scala/xml/parsing/MarkupParser.scala index 2de0d1cbf3..7f104f44f1 100644 --- a/src/library/scala/xml/parsing/MarkupParser.scala +++ b/src/library/scala/xml/parsing/MarkupParser.scala @@ -101,13 +101,13 @@ trait MarkupParser requires (MarkupParser with MarkupHandler) extends AnyRef wit xSpace; - m.getValue("version") match { + m("version") match { case null => ; case Text("1.0") => info_ver = Some("1.0"); n = n + 1; case _ => reportSyntaxError("cannot deal with versions != 1.0"); } - m.getValue("encoding") match { + m("encoding") match { case null => ; case Text(enc) => if (!isValidIANAEncoding(enc.toString())) reportSyntaxError("\"" + enc + "\" is not a valid encoding"); @@ -116,7 +116,7 @@ trait MarkupParser requires (MarkupParser with MarkupHandler) extends AnyRef wit n = n + 1; } } - m.getValue("standalone") match { + m("standalone") match { case null => ; case Text("yes") => info_stdl = Some(true); n = n + 1; case Text("no") => info_stdl = Some(false); n = n + 1; @@ -139,13 +139,13 @@ trait MarkupParser requires (MarkupParser with MarkupHandler) extends AnyRef wit var m = xmlProcInstr(); var n = 0; - m.getValue("version") match { + m("version") match { case null => ; case Text("1.0") => info_ver = Some("1.0"); n = n + 1; case _ => reportSyntaxError("cannot deal with versions != 1.0"); } - m.getValue("encoding") match { + m("encoding") match { case null => ; case Text(enc) => if (!isValidIANAEncoding(enc.toString())) reportSyntaxError("\"" + enc + "\" is not a valid encoding"); diff --git a/test/files/jvm/xml01.check b/test/files/jvm/xml01.check index b535e2c511..5e9ee2aed0 100644 --- a/test/files/jvm/xml01.check +++ b/test/files/jvm/xml01.check @@ -19,6 +19,9 @@ passed ok passed ok <book><author>Peter Buneman</author><author>Dan Suciu</author><title>Data on ze web</title></book> passed ok +-- group nodes +<f><a></a><b></b><c></c></f> +<a></a><f><a></a><b></b><c></c></f><a></a><b></b><c></c> attribute value normalization passed ok passed ok diff --git a/test/files/jvm/xml01.scala b/test/files/jvm/xml01.scala index 8eccdcbae9..3ba0bbd193 100644 --- a/test/files/jvm/xml01.scala +++ b/test/files/jvm/xml01.scala @@ -180,6 +180,15 @@ object Test { ) ); + // test group node + Console println "-- group nodes" + val zx1: Node = Group { <a/><b/><c/> } + val zy1 = <f>{zx1}</f> + Console println zy1.toString() + + val zx2: Node = Group { List(<a/>,zy1,zx1) } + Console println zx2.toString() + // test unicode escapes backslash u Console println ("attribute value normalization"); diff --git a/test/files/jvm/xmlstuff.scala b/test/files/jvm/xmlstuff.scala index 0d1aad5fac..7c66068b5a 100644 --- a/test/files/jvm/xmlstuff.scala +++ b/test/files/jvm/xmlstuff.scala @@ -61,13 +61,16 @@ passed ok </foo>; val pelems_1 = for( val x <- p \ "bar"; val y <- p \ "baz" ) yield { - Text(x.attribute("value").toString() + y.attribute("bazValue").toString()+ "!") + Text(x.attributes("value").toString() + y.attributes("bazValue").toString()+ "!") }; val pelems_2 = new NodeSeq { val theSeq = List(Text("38!"),Text("58!")) }; assertSameElements(pelems_1, pelems_2); - assertSameElements( - p \\ "@value", new NodeSeq { val theSeq = List(Text("3"), Text("5")) } - ); + + assertEquals(p \\ "@bazValue", Text("8")) + // the following won't work anymore because of group nodes + //assertSameElements( + // p \\ "@value", new NodeSeq { val theSeq = List(Text("3"), Text("5")) } + //); /* // more test cases !!! |