diff options
author | Paul Phillips <paulp@improving.org> | 2009-06-02 18:10:30 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-06-02 18:10:30 +0000 |
commit | c9bc955f520997e50797a83be75cfa3497fd018e (patch) | |
tree | 78036a2a163827d9c18a399139d0b568b8b0f753 /src/library | |
parent | 520483071d70c8e2ab989dd2a9f6db0f9ceaf58b (diff) | |
download | scala-c9bc955f520997e50797a83be75cfa3497fd018e.tar.gz scala-c9bc955f520997e50797a83be75cfa3497fd018e.tar.bz2 scala-c9bc955f520997e50797a83be75cfa3497fd018e.zip |
Massive XML simplifications.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/xml/Atom.scala | 19 | ||||
-rw-r--r-- | src/library/scala/xml/Comment.scala | 2 | ||||
-rw-r--r-- | src/library/scala/xml/Elem.scala | 36 | ||||
-rw-r--r-- | src/library/scala/xml/EntityRef.scala | 16 | ||||
-rw-r--r-- | src/library/scala/xml/Node.scala | 8 | ||||
-rw-r--r-- | src/library/scala/xml/NodeSeq.scala | 128 | ||||
-rw-r--r-- | src/library/scala/xml/ProcInstr.scala | 2 | ||||
-rw-r--r-- | src/library/scala/xml/Utility.scala | 4 | ||||
-rw-r--r-- | src/library/scala/xml/transform/BasicTransformer.scala | 2 |
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 |