summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2006-10-14 13:31:12 +0000
committerBurak Emir <emir@epfl.ch>2006-10-14 13:31:12 +0000
commit470f990722777041a475de2e5cf02ca4504a2237 (patch)
tree4527d5a708f563c53ffcc1e37f908c76062cd201
parentf1208fc000438bb03bbb18011659dd4ca25d1127 (diff)
downloadscala-470f990722777041a475de2e5cf02ca4504a2237.tar.gz
scala-470f990722777041a475de2e5cf02ca4504a2237.tar.bz2
scala-470f990722777041a475de2e5cf02ca4504a2237.zip
xml improvements for 2.2.1 (see changes)
-rw-r--r--docs/examples/xml/phonebook/embeddedBook.scala26
-rw-r--r--docs/examples/xml/phonebook/phonebook.scala38
-rw-r--r--docs/examples/xml/phonebook/phonebook1.scala21
-rw-r--r--docs/examples/xml/phonebook/phonebook2.scala25
-rw-r--r--docs/examples/xml/phonebook/phonebook3.scala96
-rw-r--r--docs/examples/xml/phonebook/verboseBook.scala24
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala48
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala38
-rw-r--r--src/library/scala/xml/Group.scala1
-rw-r--r--src/library/scala/xml/PrettyPrinter.scala1
-rw-r--r--src/library/scala/xml/UnprefixedAttribute.scala2
-rw-r--r--src/library/scala/xml/Utility.scala43
-rw-r--r--test/files/jvm/xml01.check3
-rw-r--r--test/files/jvm/xml01.scala9
-rw-r--r--test/files/jvm/xml02.scala3
-rw-r--r--test/files/jvm/xmlattr.check2
-rw-r--r--test/files/jvm/xmlattr.scala6
-rw-r--r--test/files/run/unittest_xml.scala55
19 files changed, 416 insertions, 27 deletions
diff --git a/docs/examples/xml/phonebook/embeddedBook.scala b/docs/examples/xml/phonebook/embeddedBook.scala
new file mode 100644
index 0000000000..8ea9628212
--- /dev/null
+++ b/docs/examples/xml/phonebook/embeddedBook.scala
@@ -0,0 +1,26 @@
+/* examples/phonebook/embeddedBook.scala */
+package phonebook
+
+object embeddedBook {
+
+ val company = <a href="http://acme.org">ACME</a>
+ val first = "Burak"
+ val last = "Emir"
+ val location = "work"
+
+ val embBook =
+ <phonebook>
+ <descr>
+ This is the <b>phonebook</b> of the
+ {company} corporation.
+ </descr>
+ <entry>
+ <name>{ first+" "+last }</name>
+ <phone where={ location }>+41 21 693 68 {val x = 60 + 7; x}</phone>
+ </entry>
+ </phonebook>;
+
+ def main(args: Array[String]) =
+ Console.println( embBook )
+
+}
diff --git a/docs/examples/xml/phonebook/phonebook.scala b/docs/examples/xml/phonebook/phonebook.scala
new file mode 100644
index 0000000000..4813c2d20d
--- /dev/null
+++ b/docs/examples/xml/phonebook/phonebook.scala
@@ -0,0 +1,38 @@
+package phonebook ;
+
+object phonebook {
+
+ val labPhoneBook =
+ <phonebook>
+ <descr>
+ This is the <b>phonebook</b> of the
+ <a href="http://acme.org">ACME</a> corporation.
+ </descr>
+ <entry>
+ <name>Burak</name>
+ <phone where="work"> +41 21 693 68 67</phone>
+ <phone where="mobile">+41 79 602 23 23</phone>
+ </entry>
+ </phonebook>;
+
+ Console.println( labPhoneBook );
+
+ // XML is immutable - adding an element
+
+ import scala.xml.{ Node, Text };
+
+ def add( phonebook:Node, newEntry:Node ):Node = phonebook match {
+ case <phonebook>{ ch @ _* }</phonebook> =>
+ <phonebook>{ ch }{ newEntry }</phonebook>
+ }
+
+ val pb2 =
+ add( labPhoneBook,
+ <entry>
+ <name>Kim</name>
+ <phone where="work"> +41 21 111 11 11</phone>
+ </entry> );
+
+ def main(args:Array[String]) = Console.println( pb2 );
+
+}
diff --git a/docs/examples/xml/phonebook/phonebook1.scala b/docs/examples/xml/phonebook/phonebook1.scala
new file mode 100644
index 0000000000..3a7a165202
--- /dev/null
+++ b/docs/examples/xml/phonebook/phonebook1.scala
@@ -0,0 +1,21 @@
+/* examples/phonebook/phonebook1.scala */
+package phonebook
+
+object phonebook1 {
+
+ val labPhoneBook =
+ <phonebook>
+ <descr>
+ This is the <b>phonebook</b> of the
+ <a href="http://acme.org">ACME</a> corporation.
+ </descr>
+ <entry>
+ <name>Burak Emir</name>
+ <phone where="work">+41 21 693 68 67</phone>
+ </entry>
+ </phonebook>;
+
+ def main(args: Array[String]) =
+ Console.println( labPhoneBook )
+
+}
diff --git a/docs/examples/xml/phonebook/phonebook2.scala b/docs/examples/xml/phonebook/phonebook2.scala
new file mode 100644
index 0000000000..ba50379369
--- /dev/null
+++ b/docs/examples/xml/phonebook/phonebook2.scala
@@ -0,0 +1,25 @@
+/* examples/xml/phonebook/phonebook2.scala */
+package phonebook;
+
+object phonebook2 {
+
+ import scala.xml.Node
+
+ /** adds an entry to a phonebook */
+ def add( p: Node, newEntry: Node ): Node = p match {
+
+ case <phonebook>{ ch @ _* }</phonebook> =>
+
+ <phonebook>{ ch }{ newEntry }</phonebook>
+ }
+
+ val pb2 =
+ add( phonebook1.labPhoneBook,
+ <entry>
+ <name>Kim</name>
+ <phone where="work">+41 21 111 11 11</phone>
+ </entry> );
+
+ def main( args: Array[String] ) =
+ Console.println( pb2 )
+}
diff --git a/docs/examples/xml/phonebook/phonebook3.scala b/docs/examples/xml/phonebook/phonebook3.scala
new file mode 100644
index 0000000000..ec49d450f4
--- /dev/null
+++ b/docs/examples/xml/phonebook/phonebook3.scala
@@ -0,0 +1,96 @@
+/* examples/xml/phonebook/phonebook3.scala */
+package phonebook
+
+object phonebook3 {
+
+ import scala.xml.{Elem, Node, Text}
+ import scala.xml.Utility.view
+ import scala.xml.PrettyPrinter
+ import Node.NoAttributes
+
+ /* finds entry for Name, Where, changes it, or adds if not present */
+ def change ( phonebook: Node, Name: String, Where: String, newPhone: String ) = {
+
+ /** returns true if this element's first child is the right 'name'
+ * x is treated a if it was a singleton sequence here.
+ */
+ def hasName ( x: Seq[Node] ) = x(0).child.elements.next match {
+ case <name>{ Text(Name) }</name> => true
+ case _ => false
+ }
+
+ /** returns true if this element has the right 'where' attribute
+ * y is treated a if it was a singleton sequence here.
+ * n.attribute(s) is the same as n.attributes.get(s)
+ */
+ def hasWhere ( y: Node ) = y.attribute("where") match {
+ case Some(Text(Where)) => true
+ case None => false
+ }
+
+ /** returns true if this element has the right 'where' attribute
+ * the apply method of MetaData (n.attributes) returns raw a
+ * sequence of nodes.
+ */
+ def hasWhere2 ( y: Node ) = y.attributes("where") match {
+ case null => false
+ case Text(Where) => true
+ case _ => false
+ }
+
+
+ /** walks through tree, returns changed/copied updated tree */
+ def copyOrChange ( ch: Iterator[Node] ):List[Node] = {
+ for( val c <- ch ) yield c match {
+
+ case x @ <entry>{ ch1 @ _* }</entry> if hasName( x ) =>
+ val it = ch1.elements;
+ val nameElem:Seq[Node] = it.next; // grab 'name' element
+ val ch2 = nameElem concat copyOrChange( it ); // concat with updated seq
+
+ if( ch1 == ch2 ) // not present: add as first entry
+
+ <entry>
+ <name>{ Name }</name>
+ <phone where={ Where }>{ newPhone }</phone>
+ { ch1 }
+ </entry>
+
+ else // was present and changed
+
+ <entry>
+ { ch2 }
+ </entry>
+
+ case y @ <phone>{ _* }</phone> if hasWhere( y ) =>
+ Console.println("c = "+c);
+ <phone where={ Where }>{ newPhone }</phone>
+
+ case _ =>
+ Console.println("c = "+c);
+ Console.println("c.attributes= "+c.attributes);
+ c
+
+ }
+ }.toList ; // for ... yield ... returns Iterator, convert to list
+
+ // decompose phonebook, apply updates
+ phonebook match {
+ case <phonebook>{ ch @ _* }</phonebook> =>
+ <phonebook>{ copyOrChange( ch.elements ) }</phonebook>
+ }
+
+ }
+
+ val pb2 =
+ change( phonebook1.labPhoneBook, "John", "work", "+41 55 555 55 55" );
+
+ val pp = new PrettyPrinter( 80, 5 );
+
+ def main( args:Array[String] ) = {
+ Console.println("---before---");
+ Console.println( pp.format( phonebook1.labPhoneBook ));
+ Console.println("---after---");
+ Console.println( pp.format( pb2 ));
+ }
+}
diff --git a/docs/examples/xml/phonebook/verboseBook.scala b/docs/examples/xml/phonebook/verboseBook.scala
new file mode 100644
index 0000000000..611cf5370e
--- /dev/null
+++ b/docs/examples/xml/phonebook/verboseBook.scala
@@ -0,0 +1,24 @@
+/* examples/xml/phonebook/verboseBook.scala */
+package phonebook
+
+object verboseBook {
+
+ import scala.xml.{ UnprefixedAttribute, Elem, Node, Null, Text, TopScope }
+
+ val pbookVerbose =
+ Elem(null, "phonebook", Null, TopScope,
+ Elem(null, "descr", Null, TopScope,
+ Text("This is a "),
+ Elem(null, "b", Null, TopScope, Text("sample")),
+ Text("description")
+ ),
+ Elem(null, "entry", Null, TopScope,
+ Elem(null, "name", Null, TopScope, Text("Burak Emir")),
+ Elem(null, "phone", new UnprefixedAttribute("where","work", Null), TopScope,
+ Text("+41 21 693 68 67"))
+ )
+ )
+
+ def main(args: Array[String]) =
+ Console.println( pbookVerbose )
+}
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 916736bda4..9f9ce71c7e 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -280,7 +280,7 @@ abstract class TreePrinters {
print("this")
case Select(qual @ New(tpe), name) =>
- assert(tree.symbol == null || tree.symbol.isConstructor)
+ assert(tree.symbol == null || tree.symbol.isConstructor || phase.prev.name == "parser")
print(qual)
case Select(qualifier, name) =>
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index f2e31ed6ce..0adf872a81 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -91,7 +91,14 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
nextch
val tmp = xAttributeValue(delim)
nextch
- Literal(Constant(tmp))
+ try {
+ handle.parseAttribute(pos1, tmp)
+ } catch {
+ case e =>
+ reportSyntaxError("error parsing attribute value")
+ p.errorTermTree
+ }
+
case '{' =>
nextch
xEmbeddedExpr
@@ -181,6 +188,34 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
Predef.error("this cannot happen")
}
+ def xUnparsed: Tree = {
+ val pos1 = pos
+ val sb: StringBuffer = new StringBuffer()
+ while (true) {
+ if (ch=='<' &&
+ { sb.append(ch); nextch; ch == '/' } &&
+ { sb.append(ch); nextch; ch == 'x' } &&
+ { sb.append(ch); nextch; ch == 'm' } &&
+ { sb.append(ch); nextch; ch == 'l' } &&
+ { sb.append(ch); nextch; ch == ':' } &&
+ { sb.append(ch); nextch; ch == 'u' } &&
+ { sb.append(ch); nextch; ch == 'n' } &&
+ { sb.append(ch); nextch; ch == 'p' } &&
+ { sb.append(ch); nextch; ch == 'a' } &&
+ { sb.append(ch); nextch; ch == 'r' } &&
+ { sb.append(ch); nextch; ch == 's' } &&
+ { sb.append(ch); nextch; ch == 'e' } &&
+ { sb.append(ch); nextch; ch == 'd' } &&
+ { sb.append(ch); nextch; ch == '>' }) {
+ sb.setLength(sb.length - "</xml:unparsed".length)
+ nextch
+ return handle.unparsed(pos1, sb.toString())
+ } else sb.append(ch)
+ nextch
+ }
+ Predef.error("this cannot happen")
+ }
+
/** CharRef ::= "&#" '0'..'9' {'0'..'9'} ";"
* | "&#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";"
*
@@ -339,14 +374,17 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
}
else { // handle content
xToken('>')
+ if(qname == "xml:unparsed")
+ return xUnparsed
+
debugLastStartElement.push(Pair(pos1, qname))
val ts = content
xEndTag(qname)
debugLastStartElement.pop
- if(qname=="xml:group")
- handle.group(pos1, ts)
- else
- handle.element(pos1, qname, attrMap, ts)
+ qname match {
+ case "xml:group" => handle.group(pos1, ts)
+ case _ => handle.element(pos1, qname, attrMap, ts)
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
index 3a14035312..1d6b1319a7 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
@@ -9,7 +9,7 @@ package scala.tools.nsc.ast.parser
import scala.collection.immutable.{Map, ListMap}
import scala.collection.mutable
import scala.tools.nsc.util.Position
-import scala.xml.{Text, TextBuffer}
+import scala.xml.{EntityRef, Text, TextBuffer}
import symtab.Flags.MUTABLE
/** This class builds instance of Tree that represent XML.
@@ -37,6 +37,7 @@ abstract class SymbolicXMLBuilder(make: TreeBuilder, p: Parsers # Parser, preser
def _UnprefixedAttribute = global.newTypeName("UnprefixedAttribute")
def _Elem = global.newTypeName("Elem")
def _Group = global.newTypeName("Group")
+ def _Unparsed = global.newTypeName("Unparsed")
def _Seq = global.newTypeName("Seq")
def _immutable = global.newTermName("immutable")
def _mutable = global.newTermName("mutable")
@@ -79,6 +80,7 @@ abstract class SymbolicXMLBuilder(make: TreeBuilder, p: Parsers # Parser, preser
private def _scala_xml_Elem = _scala_xml(_Elem)
private def _scala_xml_Attribute = _scala_xml(_Attribute)
private def _scala_xml_Group = _scala_xml(_Group)
+ private def _scala_xml_Unparsed = _scala_xml(_Unparsed)
/*
private def bufferToArray(buf: mutable.Buffer[Tree]): Array[Tree] = {
@@ -99,11 +101,10 @@ abstract class SymbolicXMLBuilder(make: TreeBuilder, p: Parsers # Parser, preser
protected def mkXML(pos: int, isPattern: boolean, pre: Tree, label: Tree, attrs: /*Array[*/Tree/*]*/ , scope:Tree, children: mutable.Buffer[Tree]): Tree = {
if (isPattern) {
- //val ts = new mutable.ArrayBuffer[Tree]()
convertToTextPat(children)
- atPos (pos) {
+ atPos (pos) { //@todo maybe matching on attributes, scope?
Apply( _scala_xml_Elem, List(
- pre, label, Ident( nme.WILDCARD ) /* attributes? */ , Ident( nme.WILDCARD )) /* scope? */ ::: children.toList )
+ pre, label, Ident( nme.WILDCARD ) /* md */ , Ident( nme.WILDCARD )) /* scope */ ::: children.toList )
}
} else {
var ab = List(pre, label, attrs, scope);
@@ -167,6 +168,20 @@ abstract class SymbolicXMLBuilder(make: TreeBuilder, p: Parsers # Parser, preser
case _ => t
}
+ def parseAttribute(pos: Int, s: String): Tree = {
+ val ns = xml.Utility.parseAttributeValue(s)
+ val ts:collection.mutable.ListBuffer[Tree] = new collection.mutable.ListBuffer
+ val it = ns.elements
+ while(it.hasNext) it.next match {
+ case Text(s) => ts += text(pos, s) // makeText1(Literal(Constant(s)))
+ case EntityRef(s) => ts += entityRef(pos, s)
+ }
+ ts.length match {
+ case 0 => gen.mkNil
+ case 1 => val t = ts(0); ts.clear; t
+ case _ => makeXMLseq(pos, ts)
+ }
+ }
protected def convertToTextPat(buf: mutable.Buffer[Tree]): Unit = {
var i = 0; while (i < buf.length) {
val t1 = buf(i)
@@ -208,6 +223,12 @@ abstract class SymbolicXMLBuilder(make: TreeBuilder, p: Parsers # Parser, preser
atPos(pos) { New( _scala_xml_Group, LL( makeXMLseq(pos, args))) }
}
+ /** code that constructs an unparsed node
+ */
+ def unparsed(pos: int, str: String): Tree = {
+ atPos(pos) { New( _scala_xml_Unparsed, LL( Literal(Constant(str)))) }
+ }
+
/** makes an element */
def element(pos: int, qname: String, attrMap: mutable.Map[String,Tree], args: mutable.Buffer[Tree]): Tree = {
//Console.println("SymbolicXMLBuilder::element("+pos+","+qname+","+attrMap+","+args+")");
@@ -216,10 +237,11 @@ abstract class SymbolicXMLBuilder(make: TreeBuilder, p: Parsers # Parser, preser
var tlist: List[Tree] = List()
/* pre can be null */
- def handleNamespaceBinding(pre:String , uri:Tree): Unit = {
- val t = Assign(Ident(_tmpscope), New( _scala_xml_NamespaceBinding,
- LL(Literal(Constant(pre)), uri, Ident( _tmpscope))));
- tlist = t :: tlist
+ def handleNamespaceBinding(pre:String , uri1: Tree): Unit = uri1 match {
+ case Apply(_,List(uri @ Literal(Constant(_)))) => //text
+ val t = Assign(Ident(_tmpscope), New( _scala_xml_NamespaceBinding,
+ LL(Literal(Constant(pre)), uri, Ident( _tmpscope))));
+ tlist = t :: tlist
//Console.println("SymbolicXMLBuilder::handleNamespaceBinding:");
//Console.println(t.toString());
}
diff --git a/src/library/scala/xml/Group.scala b/src/library/scala/xml/Group.scala
index c5f7911138..7ca864add7 100644
--- a/src/library/scala/xml/Group.scala
+++ b/src/library/scala/xml/Group.scala
@@ -25,6 +25,7 @@ case class Group(val nodes: Seq[Node]) extends Node {
/** structural equality */
override def equals(x: Any) = x match {
+ case z:Group => (length == z.length) && sameElements(z)
case z:Node => (length == 1) && z == apply(0)
case z:Seq[Node] => sameElements(z)
case z:String => text == z
diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala
index cd146ddd58..7ef542cbb6 100644
--- a/src/library/scala/xml/PrettyPrinter.scala
+++ b/src/library/scala/xml/PrettyPrinter.scala
@@ -196,6 +196,7 @@ class PrettyPrinter( width:Int, step:Int ) {
makeBreak()
traverse(node.child.elements, node.scope, ind + step)
makeBox(cur, etg)
+ makeBreak()
} else { // give up
makeBox(ind, test)
makeBreak()
diff --git a/src/library/scala/xml/UnprefixedAttribute.scala b/src/library/scala/xml/UnprefixedAttribute.scala
index cc5d002e84..5159c5a67f 100644
--- a/src/library/scala/xml/UnprefixedAttribute.scala
+++ b/src/library/scala/xml/UnprefixedAttribute.scala
@@ -22,7 +22,7 @@ class UnprefixedAttribute(val key: String, val value: Seq[Node], next1: MetaData
/** same as this(key, Utility.parseAttributeValue(value), next) */
def this(key: String, value: String, next: MetaData) =
- this(key, if(value!=null) Utility.parseAttributeValue(value) else {val z:NodeSeq=null;z}, next)
+ this(key, if(value!=null) Text(value) else {val z:NodeSeq=null;z}, next)
/** returns a copy of this unprefixed attribute with the given next field*/
def copy(next: MetaData) =
diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala
index ffa2cdfc03..dd189360cb 100644
--- a/src/library/scala/xml/Utility.scala
+++ b/src/library/scala/xml/Utility.scala
@@ -33,11 +33,25 @@ object Utility extends AnyRef with parsing.TokenTests {
case '>' => s.append("&gt;")
case '&' => s.append("&amp;")
case '"' => s.append("&quot;")
+ case '\'' => s.append("&apos;")
case _ => s.append(c)
}
s
}
+ /* appends unescaped string to s, amp becomes &amp; lt becomes &lt;
+ * @returns null if ref was not a predefined entity
+ */
+ final def unescape(ref: String, s: StringBuilder): StringBuilder =
+ ref match {
+ case "lt" => s.append('<')
+ case "gt" => s.append('>')
+ case "amp" => s.append('&')
+ case "quot" => s.append('"')
+ case "apos" => s.append(''')
+ case _ => null
+ }
+
/**
* Returns a set of all namespaces used in a sequence of nodes
* and all their descendants, including the empty namespaces.
@@ -265,17 +279,14 @@ object Utility extends AnyRef with parsing.TokenTests {
*/
def parseAttributeValue(value:String):Seq[Node] = {
val zs:Seq[Char] = value
- val sb = new StringBuilder()
+ val sb = new StringBuilder
+ var rfb: StringBuilder = null
val nb = new NodeBuffer()
val it = zs.elements
while(it.hasNext) {
var c = it.next
c match {
- case '&' =>
- if(sb.length() > 0) {
- nb += Text(sb.toString())
- sb.setLength(0)
- }
+ case '&' => // entity! flush buffer into text node
it.next match {
case '#' =>
c = it.next
@@ -283,20 +294,30 @@ object Utility extends AnyRef with parsing.TokenTests {
sb.append(theChar)
case x =>
- sb.append(x)
+ if(rfb==null) rfb = new StringBuilder()
+ rfb.append(x)
c = it.next
while(c != ';') {
- sb.append(c)
+ rfb.append(c)
c = it.next
}
- nb += EntityRef(sb.toString())
- sb.setLength(0)
+ val ref = rfb.toString()
+ rfb.setLength(0)
+ unescape(ref,sb) match {
+ case null =>
+ if(sb.length() > 0) { // flush buffer
+ nb += Text(sb.toString())
+ sb.setLength(0)
+ }
+ nb += EntityRef(sb.toString()) // add entityref
+ case _ =>
+ }
}
case x =>
sb.append(x)
}
}
- if(sb.length() > 0) {
+ if(sb.length() > 0) { // flush buffer
val x = Text(sb.toString())
if(nb.length == 0)
return x
diff --git a/test/files/jvm/xml01.check b/test/files/jvm/xml01.check
index 5e9ee2aed0..2a8d2e5625 100644
--- a/test/files/jvm/xml01.check
+++ b/test/files/jvm/xml01.check
@@ -22,6 +22,9 @@ 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>
+passed ok
+passed ok
+passed ok
attribute value normalization
passed ok
passed ok
diff --git a/test/files/jvm/xml01.scala b/test/files/jvm/xml01.scala
index 3558d95100..8c99cfd358 100644
--- a/test/files/jvm/xml01.scala
+++ b/test/files/jvm/xml01.scala
@@ -189,6 +189,15 @@ object Test {
val zx2: Node = Group { List(<a/>,zy1,zx1) }
Console println zx2.toString()
+ val zz1 = <xml:group><a/><b/><c/></xml:group>
+
+ assertTrue(zx1 == zz1)
+ assertTrue(zz1.length == 3)
+
+ // unparsed
+
+ val uup = <xml:unparsed>&<<>""^%@$!#</xml:unparsed>
+ assertTrue(uup == "&<<>\"\"^%@$!#")
// test unicode escapes backslash u
Console println ("attribute value normalization");
diff --git a/test/files/jvm/xml02.scala b/test/files/jvm/xml02.scala
index cbc9b5041b..d0d97e64eb 100644
--- a/test/files/jvm/xml02.scala
+++ b/test/files/jvm/xml02.scala
@@ -21,7 +21,8 @@ def main(args:Array[String]) = {
Console.println("three");
assertEquals(bx \ "@foo", "bar&x")
Console.println("four");
- assertSameElements(bx \ "@foo", List(xml.Text("bar"),xml.EntityRef("amp"),xml.Text("x")))
+ assertSameElements(bx \ "@foo", List(xml.Text("bar&x")))
+ //assertSameElements(bx \ "@foo", List(xml.Text("bar"),xml.EntityRef("amp"),xml.Text("x")))
Console.println("five");
assertEquals(bx.toString, "<hello foo=\"bar&amp;x\"></hello>")
diff --git a/test/files/jvm/xmlattr.check b/test/files/jvm/xmlattr.check
index a1841a78ef..bebcb45081 100644
--- a/test/files/jvm/xmlattr.check
+++ b/test/files/jvm/xmlattr.check
@@ -8,3 +8,5 @@ true
None
null
+<b x="&amp;"></b>
+<b x="&amp;"></b>
diff --git a/test/files/jvm/xmlattr.scala b/test/files/jvm/xmlattr.scala
index 9801e05357..c34f66eafc 100644
--- a/test/files/jvm/xmlattr.scala
+++ b/test/files/jvm/xmlattr.scala
@@ -20,4 +20,10 @@ object Test extends Application {
Console.println(x.get("foo")) // None
Console.println(x("foo")) // null
}
+
+ val x1 = <b x="&amp;"/>
+ val x2 = <b x={"&"}/>
+ Console.println(x1)
+ Console.println(x2)
+
}
diff --git a/test/files/run/unittest_xml.scala b/test/files/run/unittest_xml.scala
new file mode 100644
index 0000000000..5f7c523996
--- /dev/null
+++ b/test/files/run/unittest_xml.scala
@@ -0,0 +1,55 @@
+
+object Test {
+
+ import scala.testing.SUnit._
+ import scala.xml.{MetaData, Null, PrefixedAttribute, UnprefixedAttribute }
+
+ class MetaDataTest extends TestCase("collection.mutable.ArrayBuffer") with Assert {
+
+ import scala.xml.{TopScope, NamespaceBinding, Atom, Text }
+
+ override def runTest = {
+
+ var x: MetaData = Null
+ var s: NamespaceBinding = TopScope
+
+ // testing method def apply(uri:String, scp:NamespaceBinding, k:String): Seq[Node]
+ // def apply(k:String): Seq[Node]
+
+ assertEquals("absent element (prefixed) 1", null, x("za://foo.com", s, "bar" ))
+ assertEquals("absent element (unprefix) 1", null, x("bar"))
+
+ assertEquals("absent element (prefixed) 2", None, x.get("za://foo.com", s, "bar" ))
+ assertEquals("absent element (unprefix) 2", None, x.get("bar"))
+
+ x = new PrefixedAttribute("zo","bar", new Atom(42), x)
+ s = new NamespaceBinding("zo","za://foo.com",s)
+
+ assertEquals("present element (prefixed) 3", new Atom(42), x("za://foo.com", s, "bar" ))
+ assertEquals("present element (unprefix) 3", null, x("bar"))
+
+ assertEquals("present element (prefixed) 4", Some(new Atom(42)), x.get("za://foo.com", s, "bar" ))
+ assertEquals("present element (unprefix) 4", None, x.get("bar"))
+
+ x = new UnprefixedAttribute("bar","meaning", x)
+
+ assertEquals("present element (prefixed) 5", null, x(null, s, "bar" ))
+ assertEquals("present element (unprefix) 5", Text("meaning"), x("bar"))
+
+ assertEquals("present element (prefixed) 6", None, x.get(null, s, "bar" ))
+ assertEquals("present element (unprefix) 6", Some(Text("meaning")), x.get("bar"))
+
+ }
+ }
+
+ def main(args:Array[String]) = {
+ val ts = new TestSuite(
+ new MetaDataTest //,
+ )
+ val tr = new TestResult()
+ ts.run(tr)
+ for(val failure <- tr.failures) {
+ Console.println(failure)
+ }
+ }
+}