scala-xml icon indicating copy to clipboard operation
scala-xml copied to clipboard

Surprising filter on node failure

Open fancellu opened this issue 11 years ago • 7 comments

With the following code:

https://gist.github.com/fancellu/03bb694c920898613795


So as you can see, with hard coded XML, the filter works fine. With a seemingly equivalent structure, it doesn't find anything.

Probably due to different hashCodes, even though elements render the same

(root"number").hashCode //> Int = 1598709610 (root2"number").hashCode //> Int = 1439920665

(root"number").head.text==(root2"number").head.text //> Boolean=true

fancellu avatar Apr 28 '14 16:04 fancellu

scala> val a = <number>{2}</number>
a: scala.xml.Elem = <number>2</number>

scala> val b = <number>2</number>
b: scala.xml.Elem = <number>2</number>

scala> a == b
res0: Boolean = false

scala> (a.hashCode, b.hashCode)
res0: (Int, Int) = (-1257096872,361570984)

ScalaWilliam avatar Apr 28 '14 17:04 ScalaWilliam

Thanks William, back to my version, you can "fix" by stringifying then loading back. Ha! (I'm cringing)

(scala.xml.XML.loadString(root2.toString) "number").filter(find2)

So that is why when you're getting your XML from a string/url/file/dom, it will be fine, its just the Scala escaped stuff which seems broken.

Or. generate like this:

val root2= {for (x<- 1 to 3) yield {scala.xml.Text(x.toString)}}

{x} emits an Atom. But renders the same. Either way, it doesn't follow the principle of least surprise

fancellu avatar Apr 28 '14 17:04 fancellu

package com.scalawilliam.examples

object Equality extends App {
  val a = <number>{2}</number>
  val b = <number>2</number>
  println(a.xml_==(b))
  println(a.equals(b))
  println(a == b)
  println((<numbers><number>{2}</number><number>2</number></numbers> \ "number").distinct)
}
false
false
Set(<number>2</number>, <number>2</number>)

ScalaWilliam avatar Apr 28 '14 17:04 ScalaWilliam

package com.scalawilliam.examples

object Equality extends App {
  val number = <numbers><number>{2}</number><number>2</number></numbers> \ "number"
  val numbers = for {
    item <- number
    i <- item
    j <- i
    node <- j.child
  } yield (node, node.hashCode(), node.getClass.getName, node.map(_.asInstanceOf[scala.xml.Atom[_]].data.getClass.getName))
  numbers foreach println
}
(2,-548373507,scala.xml.Atom,List(java.lang.Integer))
(2,-301266488,scala.xml.Text,List(java.lang.String))

ScalaWilliam avatar Apr 28 '14 18:04 ScalaWilliam

   <node>{2}</node> == <node>2</node>
   > false
   <node>{Text(2.toString)}</node> == <node>2</node>
   > true
   <node>{2}</node> == <node>{2}</node> 
   >true

So if using XML literals and curly braces to inject values, best test against similar escaped value, and not what looks the same when serialized.

fancellu avatar Apr 30 '14 18:04 fancellu

get caught by it.

ant chance to fix it? it's too surprising. i was wondering what happened and spent 1-2 hrs on this.

HuStmpHrrr avatar Jan 29 '16 18:01 HuStmpHrrr

@HuStmpHrrr pull request welcome. this repo is community-maintained, the only fixes coming in these days are coming from the community.

SethTisue avatar Feb 20 '18 19:02 SethTisue