Scala XML.loadString vs literal expression
From what I can see, in_xml
and from_str
are not equals because the order of the attributes is different. This is unfortunate and due to the way the XML is created by the compiler. That causes the attributes to be different:
scala> in_xml.attributes == from_str.attributesres30: Boolean = false
You can see see that if you replace the attributes the comparison will work:
scala> in_xml.copy(attributes=from_str.attributes) == from_strres32: Boolean = true
With that said, I'm not clear why that would cause a different behavior in the code that replaces the href
attribute. In fact I suspect that something is wrong with the way attribute mapping works. For instance, if I replace the in_str
with:
val in_str = """<link type="text/css" rel="stylesheet" href="/css/main.css" xmlns="http://www.w3.org/1999/xhtml"></link>"""
It works fine. Could it be that the attribute code from Daniel only works if the attribute is in the head position of MetaData
?
Side note: unless in_xml
is null
, equals
and ==
would return the same value. The ==
version will check whether the first operand is null before calling equals
.
Some further testing:Maybe, my initial equality test is not appropriate:
in_xml == from_str
and if I test :
in_xml.equals(in_xml)
I get also get false. Maybe, I should use another testing method (like corresponds, but I did not find out what a predicate I should use as second parameter...)
That said, if I test the following in the REPL
<body id="1234"></body> == XML.loadString("<body id=\"1234\"></body>")
I get true, even without calling the equals method...
Back to my initial example: I defined a rewrite rule
def unSlash(s: String) = if (s.head == '/') s.tail else sval changeCSS = new RewriteRule { override def transform(n: Node): NodeSeq = n match { case e: Elem if (n \ "@rel").text == "stylesheet" => e.copy(attributes = mapMetaData(e.attributes) { case g @ GenAttr(_, key, Text(v), _) if key == "href" => g.copy(value = Text(unSlash(v))) case other => other }) case n => n }}
It uses the helper classes/methods defined by Daniel C. Sobral at How to change attribute on Scala XML Element. If I apply:
new RuleTransformer(changeCSS).transform(in_xml)new RuleTransformer(removeComments).transform(from_str)
I get the expected result with in_xml, but no modification with from_str...