Skip to content

Commit 487cd08

Browse files
Burak Emiradriaanm
authored andcommitted
xml improvements for 2.2.1 (see changes)
1 parent bce2cdc commit 487cd08

File tree

9 files changed

+57
-13
lines changed

9 files changed

+57
-13
lines changed

src/library/scala/xml/Group.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ case class Group(val nodes: Seq[Node]) extends Node {
2525

2626
/** structural equality */
2727
override def equals(x: Any) = x match {
28+
case z:Group => (length == z.length) && sameElements(z)
2829
case z:Node => (length == 1) && z == apply(0)
2930
case z:Seq[Node] => sameElements(z)
3031
case z:String => text == z

src/library/scala/xml/PrettyPrinter.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ class PrettyPrinter( width:Int, step:Int ) {
196196
makeBreak()
197197
traverse(node.child.elements, node.scope, ind + step)
198198
makeBox(cur, etg)
199+
makeBreak()
199200
} else { // give up
200201
makeBox(ind, test)
201202
makeBreak()

src/library/scala/xml/UnprefixedAttribute.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class UnprefixedAttribute(val key: String, val value: Seq[Node], next1: MetaData
2222

2323
/** same as this(key, Utility.parseAttributeValue(value), next) */
2424
def this(key: String, value: String, next: MetaData) =
25-
this(key, if(value!=null) Utility.parseAttributeValue(value) else {val z:NodeSeq=null;z}, next)
25+
this(key, if(value!=null) Text(value) else {val z:NodeSeq=null;z}, next)
2626

2727
/** returns a copy of this unprefixed attribute with the given next field*/
2828
def copy(next: MetaData) =

src/library/scala/xml/Utility.scala

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,25 @@ object Utility extends AnyRef with parsing.TokenTests {
3333
case '>' => s.append(">")
3434
case '&' => s.append("&")
3535
case '"' => s.append(""")
36+
case '\'' => s.append("'")
3637
case _ => s.append(c)
3738
}
3839
s
3940
}
4041

42+
/* appends unescaped string to s, amp becomes & lt becomes <
43+
* @returns null if ref was not a predefined entity
44+
*/
45+
final def unescape(ref: String, s: StringBuilder): StringBuilder =
46+
ref match {
47+
case "lt" => s.append('<')
48+
case "gt" => s.append('>')
49+
case "amp" => s.append('&')
50+
case "quot" => s.append('"')
51+
case "apos" => s.append(''')
52+
case _ => null
53+
}
54+
4155
/**
4256
* Returns a set of all namespaces used in a sequence of nodes
4357
* and all their descendants, including the empty namespaces.
@@ -265,38 +279,45 @@ object Utility extends AnyRef with parsing.TokenTests {
265279
*/
266280
def parseAttributeValue(value:String):Seq[Node] = {
267281
val zs:Seq[Char] = value
268-
val sb = new StringBuilder()
282+
val sb = new StringBuilder
283+
var rfb: StringBuilder = null
269284
val nb = new NodeBuffer()
270285
val it = zs.elements
271286
while(it.hasNext) {
272287
var c = it.next
273288
c match {
274-
case '&' =>
275-
if(sb.length() > 0) {
276-
nb += Text(sb.toString())
277-
sb.setLength(0)
278-
}
289+
case '&' => // entity! flush buffer into text node
279290
it.next match {
280291
case '#' =>
281292
c = it.next
282293
val theChar = parseCharRef ({ ()=> c },{ () => c = it.next },{s => throw new RuntimeException(s)})
283294
sb.append(theChar)
284295

285296
case x =>
286-
sb.append(x)
297+
if(rfb==null) rfb = new StringBuilder()
298+
rfb.append(x)
287299
c = it.next
288300
while(c != ';') {
289-
sb.append(c)
301+
rfb.append(c)
290302
c = it.next
291303
}
292-
nb += EntityRef(sb.toString())
293-
sb.setLength(0)
304+
val ref = rfb.toString()
305+
rfb.setLength(0)
306+
unescape(ref,sb) match {
307+
case null =>
308+
if(sb.length() > 0) { // flush buffer
309+
nb += Text(sb.toString())
310+
sb.setLength(0)
311+
}
312+
nb += EntityRef(sb.toString()) // add entityref
313+
case _ =>
314+
}
294315
}
295316
case x =>
296317
sb.append(x)
297318
}
298319
}
299-
if(sb.length() > 0) {
320+
if(sb.length() > 0) { // flush buffer
300321
val x = Text(sb.toString())
301322
if(nb.length == 0)
302323
return x

test/files/jvm/xml01.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ passed ok
2222
-- group nodes
2323
<f><a></a><b></b><c></c></f>
2424
<a></a><f><a></a><b></b><c></c></f><a></a><b></b><c></c>
25+
passed ok
26+
passed ok
27+
passed ok
2528
attribute value normalization
2629
passed ok
2730
passed ok

test/files/jvm/xml01.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,15 @@ object Test {
189189
val zx2: Node = Group { List(<a/>,zy1,zx1) }
190190
Console println zx2.toString()
191191

192+
val zz1 = <xml:group><a/><b/><c/></xml:group>
193+
194+
assertTrue(zx1 == zz1)
195+
assertTrue(zz1.length == 3)
196+
197+
// unparsed
198+
199+
val uup = <xml:unparsed>&<<>""^%@$!#</xml:unparsed>
200+
assertTrue(uup == "&<<>\"\"^%@$!#")
192201
// test unicode escapes backslash u
193202

194203
Console println ("attribute value normalization");

test/files/jvm/xml02.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ def main(args:Array[String]) = {
2121
Console.println("three");
2222
assertEquals(bx \ "@foo", "bar&x")
2323
Console.println("four");
24-
assertSameElements(bx \ "@foo", List(xml.Text("bar"),xml.EntityRef("amp"),xml.Text("x")))
24+
assertSameElements(bx \ "@foo", List(xml.Text("bar&x")))
25+
//assertSameElements(bx \ "@foo", List(xml.Text("bar"),xml.EntityRef("amp"),xml.Text("x")))
2526

2627
Console.println("five");
2728
assertEquals(bx.toString, "<hello foo=\"bar&amp;x\"></hello>")

test/files/jvm/xmlattr.check

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ true
88

99
None
1010
null
11+
<b x="&amp;"></b>
12+
<b x="&amp;"></b>

test/files/jvm/xmlattr.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,10 @@ object Test extends Application {
2020
Console.println(x.get("foo")) // None
2121
Console.println(x("foo")) // null
2222
}
23+
24+
val x1 = <b x="&amp;"/>
25+
val x2 = <b x={"&"}/>
26+
Console.println(x1)
27+
Console.println(x2)
28+
2329
}

0 commit comments

Comments
 (0)