summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library/scala/xml/Atom.scala4
-rw-r--r--src/library/scala/xml/Comment.scala3
-rw-r--r--src/library/scala/xml/Elem.scala5
-rw-r--r--src/library/scala/xml/EntityRef.scala3
-rw-r--r--src/library/scala/xml/Group.scala2
-rw-r--r--src/library/scala/xml/Node.scala6
-rw-r--r--src/library/scala/xml/ProcInstr.scala3
-rw-r--r--src/library/scala/xml/Utility.scala2
-rw-r--r--src/library/scala/xml/transform/BasicTransformer.scala131
-rw-r--r--src/library/scala/xml/transform/RuleTransformer.scala12
-rw-r--r--test/files/run/bug2124.check1
-rw-r--r--test/files/run/bug2124.scala25
-rw-r--r--test/files/run/bug2125.check1
-rw-r--r--test/files/run/bug2125.scala25
14 files changed, 96 insertions, 127 deletions
diff --git a/src/library/scala/xml/Atom.scala b/src/library/scala/xml/Atom.scala
index 6f48d64f12..44770bce1a 100644
--- a/src/library/scala/xml/Atom.scala
+++ b/src/library/scala/xml/Atom.scala
@@ -23,7 +23,9 @@ class Atom[+A](val data: A) extends SpecialNode
if (data.asInstanceOf[AnyRef] == null)
throw new IllegalArgumentException("cannot construct Atom(null)")
- final override def collectNamespacesAndDontTransform = false
+ final override def doCollectNamespaces = false
+ final override def doTransform = false
+
def label = "#PCDATA"
override def equals(x: Any) = x match {
diff --git a/src/library/scala/xml/Comment.scala b/src/library/scala/xml/Comment.scala
index 421b5b4afb..c1b7c6645c 100644
--- a/src/library/scala/xml/Comment.scala
+++ b/src/library/scala/xml/Comment.scala
@@ -20,7 +20,8 @@ case class Comment(commentText: String) extends SpecialNode
{
def label = "#REM"
override def text = ""
- final override def collectNamespacesAndDontTransform = false
+ final override def doCollectNamespaces = false
+ final override def doTransform = false
if (commentText contains "--")
throw new IllegalArgumentException("text contains \"--\"")
diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala
index 2392e1a002..28032fcc30 100644
--- a/src/library/scala/xml/Elem.scala
+++ b/src/library/scala/xml/Elem.scala
@@ -49,6 +49,9 @@ class Elem(
val child: Node*)
extends Node
{
+ final override def doCollectNamespaces = true
+ final override def doTransform = true
+
if ((null != prefix) && 0 == prefix.length())
throw new IllegalArgumentException("prefix of zero length, use null instead")
@@ -59,8 +62,6 @@ extends Node
// setting namespace scope if necessary
// cleaning adjacent text nodes if necessary
- final override def collectNamespacesAndDontTransform = true
-
override def hashCode(): Int =
Utility.hashCode(prefix, label, attributes.hashCode(), scope.hashCode(), child)
diff --git a/src/library/scala/xml/EntityRef.scala b/src/library/scala/xml/EntityRef.scala
index 3300af2963..1f241aa54c 100644
--- a/src/library/scala/xml/EntityRef.scala
+++ b/src/library/scala/xml/EntityRef.scala
@@ -19,7 +19,8 @@ package scala.xml
* @param text the text contained in this node.
*/
case class EntityRef(entityName: String) extends SpecialNode {
- final override def collectNamespacesAndDontTransform = false
+ final override def doCollectNamespaces = false
+ final override def doTransform = false
def label = "#ENTITY"
override def text = entityName match {
diff --git a/src/library/scala/xml/Group.scala b/src/library/scala/xml/Group.scala
index 7e4b983ec6..99a9f8c95d 100644
--- a/src/library/scala/xml/Group.scala
+++ b/src/library/scala/xml/Group.scala
@@ -18,7 +18,7 @@ package scala.xml
*/
@serializable
case class Group(val nodes: Seq[Node]) extends Node {
-
+ // final override def doTransform = false
override def theSeq = nodes
/** XXX this is ridiculous, we can't do equality like this. */
diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala
index 2b6427ae74..618c4de8d2 100644
--- a/src/library/scala/xml/Node.scala
+++ b/src/library/scala/xml/Node.scala
@@ -48,9 +48,9 @@ abstract class Node extends NodeSeq {
*/
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
+ /** The logic formerly found in typeTag$, as best I could infer it. */
+ def doCollectNamespaces = true // if (tag >= 0) DO collect namespaces
+ def doTransform = true // if (tag < 0) DO NOT transform
/**
* method returning the namespace bindings of this node. by default, this
diff --git a/src/library/scala/xml/ProcInstr.scala b/src/library/scala/xml/ProcInstr.scala
index e70b606fb3..a4bff34271 100644
--- a/src/library/scala/xml/ProcInstr.scala
+++ b/src/library/scala/xml/ProcInstr.scala
@@ -25,7 +25,8 @@ case class ProcInstr(target:String, proctext:String) extends SpecialNode
if (text.indexOf("?>") != -1)
throw new IllegalArgumentException(proctext+" may not contain \"?>\"")
- final override def collectNamespacesAndDontTransform = false
+ final override def doCollectNamespaces = false
+ final override def doTransform = 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 17584ee40d..8e4c42c255 100644
--- a/src/library/scala/xml/Utility.scala
+++ b/src/library/scala/xml/Utility.scala
@@ -143,7 +143,7 @@ object Utility extends AnyRef with parsing.TokenTests
* @param set ...
*/
def collectNamespaces(n: Node, set: Set[String]) {
- if (n.collectNamespacesAndDontTransform) {
+ if (n.doCollectNamespaces) {
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 e566e27d02..90e248019d 100644
--- a/src/library/scala/xml/transform/BasicTransformer.scala
+++ b/src/library/scala/xml/transform/BasicTransformer.scala
@@ -18,136 +18,55 @@ package scala.xml.transform
*/
abstract class BasicTransformer extends Function1[Node,Node]
{
- protected case class NeedsCopy(result: Seq[Node]) extends Throwable
-
- /** Returns a new node buffer with the first <code>pos</code> elements
- * from <code>ns</code>.
- *
- * @param pos ..
- * @param ns ..
- * @return ..
- */
- protected def buffer(pos: Int, ns: Seq[Node]): NodeBuffer = {
- val nb = new NodeBuffer()
- var jt = ns.iterator
- var j = 0; while (j < pos-1) {
- nb.append(jt.next)
- j += 1
- }
- nb
- }
-
- /** Turns a nodebuffer into a sequence, so hashcode works.
- *
- * @param nb ..
- * @return ..
- */
- protected def freeze(nb: NodeBuffer): Seq[Node] = {
- val arr = new Array[Node](nb.length)
- var i = 0
- val it = nb.iterator; while (it.hasNext) {
- arr(i) = it.next
- i += 1
- }
- val seq: Seq[Node] = arr
- seq
- }
-
- protected def single(ns: Seq[Node]) =
- 1 == ns.length
-
/**
* @param n ...
* @param ns ...
* @return ...
*/
protected def unchanged(n: Node, ns: Seq[Node]) =
- single(ns) && (ns.iterator.next.eq(n))
+ ns.length == 1 && (ns.head eq n)
/** Call transform(Node) for each node in ns, append results
* to NodeBuffer.
*/
- def transform(it: Iterator[Node], nb: NodeBuffer): Seq[Node] = {
- while (it.hasNext)
- nb ++= transform(it.next);
- freeze(nb)
- }
+ def transform(it: Iterator[Node], nb: NodeBuffer): Seq[Node] =
+ it.foldLeft(nb)(_ ++= transform(_)) toArray
/** Call transform(Node) to each node in ns, yield ns if nothing changes,
* otherwise a new sequence of concatenated results.
*/
def transform(ns: Seq[Node]): Seq[Node] = {
- var i = 0
- val it = ns.iterator
- try {
- while (it.hasNext) {
- val n = it.next
- val n2 = transform(n)
- if (!unchanged(n, n2)) {
- throw NeedsCopy(n2)
- }
- i += 1
- }
- ns
- } catch {
- case NeedsCopy(n2) =>
- val nb = buffer(i, ns)
- nb ++= (n2:Iterable[xml.Node])
- transform(it, nb)
+ def testForChange(n: Node): Option[Seq[Node]] = {
+ val n2 = transform(n)
+ if (unchanged(n, n2)) None
+ else Some(n2)
}
+ // if any node is changed by the transform, concatenate
+ // the unchanged nodes with a recursive call.
+ for ((n, i) <- ns.zipWithIndex ; n2 <- testForChange(n))
+ return (ns take i) ++ transform(n2)
+
+ // no change, return original sequence
+ ns
}
def transform(n: Node): Seq[Node] = {
- if (!n.collectNamespacesAndDontTransform)
- n
- else {
- val ch = n.child
- val nch = transform(ch)
- if (ch.eq(nch))
- n
- else
- Elem(n.prefix, n.label, n.attributes, n.scope, nch:_*)
+ if (n.doTransform) n match {
+ case Group(xs) => Group(transform(xs)) // un-group the hack Group tag
+ case _ =>
+ val ch = n.child
+ val nch = transform(ch)
+
+ if (ch eq nch) n
+ else Elem(n.prefix, n.label, n.attributes, n.scope, nch:_*)
}
+ else n
}
def apply(n: Node): Node = {
val seq = transform(n)
- if (!single(seq))
+ if (seq.length > 1)
throw new UnsupportedOperationException("transform must return single node for root");
- else seq.iterator.next
- }
-}
-
-/*
-class IdentityTransformer extends BasicTransformer {
- override def transform(n: Node): Seq[Node] = n.match {
- case <world/> => <xml-world/>
- case _ => super.transform(n);
- }
-}
-
-object Foo with Application {
-
- val tr = new IdentityTransformer;
- val n = tr( <hello><world/></hello> );
- Console.println(n);
-
- val tr2 = new RewriteRule {
- final override val name = "A rule";
- override def transform(n: Node) = n.match {
- case <a/> => <b/><c/>
- case _ => n
- }
- }
- val tr3 = new RewriteRule {
- final override val name = "E rule";
- override def transform(n: Node) = n.match {
- case <e/> => <f><f/></f>
- case _ => n
- }
+ else seq.head
}
- val tr4 = new RuleTransformer(tr2, tr3);
- val m = tr4( <hello><a/><e/></hello> );
- Console.println(m);
}
-*/
diff --git a/src/library/scala/xml/transform/RuleTransformer.scala b/src/library/scala/xml/transform/RuleTransformer.scala
index 682d7f2f2b..52049115d5 100644
--- a/src/library/scala/xml/transform/RuleTransformer.scala
+++ b/src/library/scala/xml/transform/RuleTransformer.scala
@@ -12,14 +12,6 @@
package scala.xml.transform
class RuleTransformer(rules: RewriteRule*) extends BasicTransformer {
- override def transform(n: Node): Seq[Node] = {
- var m: Seq[Node] = super.transform(n)
- val it = rules.iterator; while (it.hasNext) {
- val rule = it.next
- val m2 = rule.transform(m)
- //if(!m2.eq(m)) Console.println("applied rule \""+rule.name+"\"");
- m = m2
- }
- m
- }
+ override def transform(n: Node): Seq[Node] =
+ rules.foldLeft(super.transform(n)) { (res, rule) => rule transform res }
}
diff --git a/test/files/run/bug2124.check b/test/files/run/bug2124.check
new file mode 100644
index 0000000000..2b8840209f
--- /dev/null
+++ b/test/files/run/bug2124.check
@@ -0,0 +1 @@
+<p><lost></lost><q></q></p>
diff --git a/test/files/run/bug2124.scala b/test/files/run/bug2124.scala
new file mode 100644
index 0000000000..ae16e66706
--- /dev/null
+++ b/test/files/run/bug2124.scala
@@ -0,0 +1,25 @@
+import scala.xml._
+
+import scala.xml.transform._
+
+object Test {
+ val sampleXml = <p><lost/><t><s><r></r></s></t></p>
+
+ def main(args: scala.Array[String]) {
+
+ println(new RuleTransformer(new RewriteRule {
+
+ override def transform(n: Node): NodeSeq = {
+ val result = n match {
+ case <t>{_*}</t> => <q/>
+
+ case n => n
+
+ }
+// println ("Rewriting '" +n+ "' to: '" + result+ "'")
+
+ result
+ }
+ }).transform(sampleXml))
+ }
+} \ No newline at end of file
diff --git a/test/files/run/bug2125.check b/test/files/run/bug2125.check
new file mode 100644
index 0000000000..2b8840209f
--- /dev/null
+++ b/test/files/run/bug2125.check
@@ -0,0 +1 @@
+<p><lost></lost><q></q></p>
diff --git a/test/files/run/bug2125.scala b/test/files/run/bug2125.scala
new file mode 100644
index 0000000000..053798e3db
--- /dev/null
+++ b/test/files/run/bug2125.scala
@@ -0,0 +1,25 @@
+import scala.xml._
+
+import scala.xml.transform._
+
+object Test {
+
+ val sampleXml = <xml:group><p><lost/><t><s><r></r></s></t></p></xml:group>
+
+ def main(args: scala.Array[String]) {
+ println(new RuleTransformer(new RewriteRule {
+
+ override def transform(n: Node): NodeSeq = {
+
+ val result = n match {
+
+ case <t>{_*}</t> => <q/>
+
+ case n => n
+ }
+// println ("Rewriting '" +n+ "' to: '" + result+ "'")
+ result
+ }
+ }).transform(sampleXml))
+ }
+} \ No newline at end of file