summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-06-02 18:10:30 +0000
committerPaul Phillips <paulp@improving.org>2009-06-02 18:10:30 +0000
commitc9bc955f520997e50797a83be75cfa3497fd018e (patch)
tree78036a2a163827d9c18a399139d0b568b8b0f753
parent520483071d70c8e2ab989dd2a9f6db0f9ceaf58b (diff)
downloadscala-c9bc955f520997e50797a83be75cfa3497fd018e.tar.gz
scala-c9bc955f520997e50797a83be75cfa3497fd018e.tar.bz2
scala-c9bc955f520997e50797a83be75cfa3497fd018e.zip
Massive XML simplifications.
-rw-r--r--src/library/scala/xml/Atom.scala19
-rw-r--r--src/library/scala/xml/Comment.scala2
-rw-r--r--src/library/scala/xml/Elem.scala36
-rw-r--r--src/library/scala/xml/EntityRef.scala16
-rw-r--r--src/library/scala/xml/Node.scala8
-rw-r--r--src/library/scala/xml/NodeSeq.scala128
-rw-r--r--src/library/scala/xml/ProcInstr.scala2
-rw-r--r--src/library/scala/xml/Utility.scala4
-rw-r--r--src/library/scala/xml/transform/BasicTransformer.scala2
9 files changed, 66 insertions, 151 deletions
diff --git a/src/library/scala/xml/Atom.scala b/src/library/scala/xml/Atom.scala
index aeb2dedeb3..6f48d64f12 100644
--- a/src/library/scala/xml/Atom.scala
+++ b/src/library/scala/xml/Atom.scala
@@ -18,26 +18,19 @@ package scala.xml
* @param text the text contained in this node, may not be <code>null</code>.
*/
@serializable
-class Atom[+A](val data: A) extends SpecialNode {
+class Atom[+A](val data: A) extends SpecialNode
+{
+ if (data.asInstanceOf[AnyRef] == null)
+ throw new IllegalArgumentException("cannot construct Atom(null)")
- data.asInstanceOf[AnyRef] match {
- case null => new IllegalArgumentException("cannot construct Atom(null)")
- case _ =>
- }
- final override def typeTag$: Int = -1
-
- /** the constant "#PCDATA"
- */
+ final override def collectNamespacesAndDontTransform = false
def label = "#PCDATA"
override def equals(x: Any) = x match {
case s:Atom[_] => data == s.data
case _ => false
}
-
- /** hashcode for this Text */
- override def hashCode() =
- data.hashCode()
+ override def hashCode() = data.hashCode()
/** Returns text, with some characters escaped according to the XML
* specification.
diff --git a/src/library/scala/xml/Comment.scala b/src/library/scala/xml/Comment.scala
index 582b12d032..2a932b90f8 100644
--- a/src/library/scala/xml/Comment.scala
+++ b/src/library/scala/xml/Comment.scala
@@ -18,7 +18,7 @@ package scala.xml
*/
case class Comment(commentText: String) extends SpecialNode {
- final override def typeTag$: Int = -3
+ final override def collectNamespacesAndDontTransform = false
if (commentText.indexOf("--") != -1)
throw new IllegalArgumentException("text containts \"--\"")
diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala
index 85bddbef16..2392e1a002 100644
--- a/src/library/scala/xml/Elem.scala
+++ b/src/library/scala/xml/Elem.scala
@@ -19,16 +19,15 @@ package scala.xml
* Copyright 2008 Google Inc. All Rights Reserved.
* @author Burak Emir <bqe@google.com>
*/
-object Elem {
-
+object Elem
+{
def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) =
new Elem(prefix,label,attributes,scope,child:_*)
def unapplySeq(n:Node) = if (n.isInstanceOf[SpecialNode] || n.isInstanceOf[Group]) None else
- Some(Tuple5(n.prefix, n.label, n.attributes, n.scope, n.child))
-
-
+ Some((n.prefix, n.label, n.attributes, n.scope, n.child))
}
+
/** The case class <code>Elem</code> extends the <code>Node</code> class,
* providing an immutable data object representing an XML element.
*
@@ -41,13 +40,15 @@ object Elem {
* Copyright 2008 Google Inc. All Rights Reserved.
* @author Burak Emir <bqe@google.com>
*/
-// "val" is redundant for non-overriding arguments
-@serializable class Elem(override val prefix: String,
- val label: String,
- override val attributes: MetaData,
- override val scope: NamespaceBinding,
- val child: Node*) extends Node {
-
+@serializable
+class Elem(
+ override val prefix: String,
+ val label: String,
+ override val attributes: MetaData,
+ override val scope: NamespaceBinding,
+ val child: Node*)
+extends Node
+{
if ((null != prefix) && 0 == prefix.length())
throw new IllegalArgumentException("prefix of zero length, use null instead")
@@ -58,7 +59,7 @@ object Elem {
// setting namespace scope if necessary
// cleaning adjacent text nodes if necessary
- final override def typeTag$: Int = 0
+ final override def collectNamespacesAndDontTransform = true
override def hashCode(): Int =
Utility.hashCode(prefix, label, attributes.hashCode(), scope.hashCode(), child)
@@ -78,12 +79,5 @@ object Elem {
/** Returns concatenation of <code>text(n)</code> for each child
* <code>n</code>.
*/
- override def text = {
- val sb = new StringBuilder()
- val it = child.iterator
- while (it.hasNext)
- sb.append(it.next.text)
- sb.toString()
- }
-
+ override def text = child map (_.text) mkString
}
diff --git a/src/library/scala/xml/EntityRef.scala b/src/library/scala/xml/EntityRef.scala
index f660695ae1..3300af2963 100644
--- a/src/library/scala/xml/EntityRef.scala
+++ b/src/library/scala/xml/EntityRef.scala
@@ -19,23 +19,9 @@ package scala.xml
* @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"
- */
+ final override def collectNamespacesAndDontTransform = false
def label = "#ENTITY"
- override def hashCode() = entityName.hashCode()
-
- /** ...
- */
override def text = entityName match {
case "lt" => "<"
case "gt" => ">"
diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala
index c5909130eb..d022d9f8b8 100644
--- a/src/library/scala/xml/Node.scala
+++ b/src/library/scala/xml/Node.scala
@@ -25,7 +25,7 @@ object Node {
/** the empty namespace */
val EmptyNamespace = ""
- def unapplySeq(n: Node) = Some(Tuple3(n.label, n.attributes, n.child))
+ def unapplySeq(n: Node) = Some((n.label, n.attributes, n.child))
}
@@ -46,7 +46,11 @@ abstract class Node extends NodeSeq {
/** used internally. Atom/Molecule = -1 PI = -2 Comment = -3 EntityRef = -5
*/
- def typeTag$: Int = 0
+ def isAtom = this.isInstanceOf[Atom[_]]
+
+ /** The logic formerly found in typeTag$, as best I could infer it.
+ * XXX obviously this name is ludicrous. */
+ def collectNamespacesAndDontTransform = true
/**
* method returning the namespace bindings of this node. by default, this
diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala
index 28d05f885b..6485ed3df7 100644
--- a/src/library/scala/xml/NodeSeq.scala
+++ b/src/library/scala/xml/NodeSeq.scala
@@ -73,58 +73,35 @@ abstract class NodeSeq extends immutable.Sequence[Node] with SequenceTemplate[No
* @param that ...
* @return ...
*/
- def \(that: String): NodeSeq = that match {
- case "_" =>
- var zs: List[Node] = Nil
- val it = this.iterator
- while (it.hasNext) {
- val x = it.next
- val jt = x.child.iterator
- while (jt.hasNext) {
- val y = jt.next
- if (y.typeTag$ != -1)
- zs = y::zs
+ def \(that: String): NodeSeq = {
+ def atResult = {
+ def fail = throw new IllegalArgumentException(that)
+ lazy val y = this(0)
+ val attr =
+ if (that.length == 1) fail
+ else if (that(1) == '{') {
+ val i = that indexOf '}'
+ if (i == -1) fail
+ val (uri, key) = (that.substring(2,i), that.substring(i+1, that.length()))
+ if (uri == "" || key == "") fail
+ else y.attribute(uri, key)
}
- }
- NodeSeq.fromSeq(zs.reverse)
-
- case _ if (that.charAt(0) == '@') && (this.length == 1) =>
- if (that.length() == 1)
- throw new IllegalArgumentException(that)
- if (that.charAt(1) == '{') {
- val i = that.indexOf('}')
- if (i == -1)
- throw new IllegalArgumentException(that)
- val (uri, key) = (that.substring(2,i), that.substring(i+1, that.length()))
- if (uri == "" || key == "")
- throw new IllegalArgumentException(that)
- val y = this(0)
- y.attribute(uri, key) match {
- case Some(x) => Group(x)
- case _ => NodeSeq.Empty
- }
- } else {
- val k = that.substring(1)
- val y = this(0)
- y.attribute(k) match {
- case Some(x) => Group(x)
- case _ => NodeSeq.Empty
- }
- }
+ else y.attribute(that.substring(1))
- case _ =>
- var zs: List[Node] = Nil
- val it = this.iterator
- while (it.hasNext) {
- val x = it.next
- val jt = x.child.iterator
- while (jt.hasNext) {
- val y = jt.next
- if (y.label == that)
- zs = y::zs
- }
+ attr match {
+ case Some(x) => Group(x)
+ case _ => NodeSeq.Empty
}
- NodeSeq.fromSeq(zs.reverse)
+ }
+
+ def makeSeq(cond: (Node) => Boolean) =
+ NodeSeq fromSeq (this flatMap (_.child) filter cond)
+
+ that match {
+ case "_" => makeSeq(!_.isAtom)
+ case _ if (that(0) == '@' && this.length == 1) => atResult
+ case _ => makeSeq(_.label == that)
+ }
}
/** projection function. Similar to XPath, use <code>this \\ 'foo</code>
@@ -142,52 +119,13 @@ abstract class NodeSeq extends immutable.Sequence[Node] with SequenceTemplate[No
* @param that ...
* @return ...
*/
- def \\ (that: String): NodeSeq = that match {
- case "_" =>
- var zs: List[Node] = Nil
- val it = this.iterator
- while (it.hasNext) {
- val x = it.next
- val jt = x.descendant_or_self.iterator
- while (jt.hasNext) {
- val y = jt.next
- if (y.typeTag$ != -1)
- zs = y::zs
- }
- }
- zs.reverse
-
- case _ if that.charAt(0) == '@' =>
- var zs: List[Node] = Nil
- val it = this.iterator
- while (it.hasNext) {
- val x = it.next
- val jt = x.descendant_or_self.iterator
- while (jt.hasNext) {
- val y = jt.next
- if (y.typeTag$ != -1) {
- val kt = (y \ that).iterator
- while (kt.hasNext) {
- zs = (kt.next)::zs
- }
- }
- }
- }
- zs.reverse
-
- case _ =>
- var zs: List[Node] = Nil
- val it = this.iterator
- while (it.hasNext) {
- val x = it.next
- val jt = x.descendant_or_self.iterator
- while (jt.hasNext) {
- val y = jt.next
- if (y.typeTag$ != -1 && y.label == that)
- zs = y::zs
- }
- }
- zs.reverse
+ def \\ (that: String): NodeSeq = {
+ def filt(cond: (Node) => Boolean) = this flatMap (_.descendant_or_self) filter cond
+ that match {
+ case "_" => filt(!_.isAtom)
+ case _ if that(0) == '@' => filt(!_.isAtom) flatMap (_ \ that)
+ case _ => filt(x => !x.isAtom && x.label == that)
+ }
}
override def toString(): String = theSeq.iterator.foldLeft ("") {
diff --git a/src/library/scala/xml/ProcInstr.scala b/src/library/scala/xml/ProcInstr.scala
index 6268ab4adc..590b14a2ec 100644
--- a/src/library/scala/xml/ProcInstr.scala
+++ b/src/library/scala/xml/ProcInstr.scala
@@ -24,7 +24,7 @@ case class ProcInstr(target:String, proctext:String) extends SpecialNode {
else if (text.indexOf("?>") != -1)
throw new IllegalArgumentException(proctext+" may not contain \"?>\"")
- final override def typeTag$: Int = -2
+ final override def collectNamespacesAndDontTransform = false
(target: Seq[Char]) match {
case Seq('X'|'x','M'|'m','L'|'l') =>
diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala
index 42f71cd981..fb308584a8 100644
--- a/src/library/scala/xml/Utility.scala
+++ b/src/library/scala/xml/Utility.scala
@@ -28,7 +28,7 @@ object Utility extends AnyRef with parsing.TokenTests
f(sb)
sb.toString
}
- private[xml] def isAtomAndNotText(x: Node) = x.isInstanceOf[Atom[_]] && !x.isInstanceOf[Text]
+ private[xml] def isAtomAndNotText(x: Node) = x.isAtom && !x.isInstanceOf[Text]
// XXX this is very ham fisted at the moment
class XMLOptions {
@@ -153,7 +153,7 @@ object Utility extends AnyRef with parsing.TokenTests
* @param set ...
*/
def collectNamespaces(n: Node, set: Set[String]) {
- if (n.typeTag$ >= 0) {
+ if (n.collectNamespacesAndDontTransform) {
set += n.namespace
for (a <- n.attributes) a match {
case _:PrefixedAttribute =>
diff --git a/src/library/scala/xml/transform/BasicTransformer.scala b/src/library/scala/xml/transform/BasicTransformer.scala
index d75b339e82..ed7aec7627 100644
--- a/src/library/scala/xml/transform/BasicTransformer.scala
+++ b/src/library/scala/xml/transform/BasicTransformer.scala
@@ -98,7 +98,7 @@ abstract class BasicTransformer extends Function1[Node,Node] {
}
def transform(n: Node): Seq[Node] = {
- if (n.typeTag$ < 0)
+ if (!n.collectNamespacesAndDontTransform)
n
else {
val ch = n.child