Scala XML.loadString 与文字表达式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4401702/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala XML.loadString vs literal expression
提问by Henri Bauer
I have been experimenting with Scala and XML and I found a strange difference in behavior between a XML tag created with XML.load (or loadString) and writing it as a literal. Here is the code :
我一直在试验 Scala 和 XML,我发现使用 XML.load(或 loadString)创建的 XML 标记与将其作为文字编写之间的行为存在奇怪的差异。这是代码:
import scala.xml._
// creating a classical link HTML tag
val in_xml = <link type="text/css" href="/css/main.css" rel="stylesheet" xmlns="http://www.w3.org/1999/xhtml"></link>
// The same as a String
val in_str = """<link type="text/css" href="/css/main.css" rel="stylesheet" xmlns="http://www.w3.org/1999/xhtml"></link>"""
// Convert the String into XML
val from_str = XML.loadString(in_str)
println("in_xml : " + in_xml)
println("from_str: "+ from_str)
println("val_xml == from_str: "+ (in_xml == from_str))
println("in_xml.getClass() == from_str.getClass(): " +
(in_xml.getClass() == from_str.getClass()))
And here, the output :
在这里,输出:
in_xml : <link href="/css/main.css" rel="stylesheet" type="text/css" xmlns="http://www.w3.org/1999/xhtml"></link>
from_str: <link rel="stylesheet" href="/css/main.css" type="text/css" xmlns="http://www.w3.org/1999/xhtml"></link>
val_xml == from_str: false
in_xml.getClass() == from_str.getClass(): true
The types are the same. But there is not equality. The order of the attributes changes. It is never the same as the original one. The attributes of the litteral are alphabetically sorted (only hazard ?).
类型是一样的。但是没有平等。属性的顺序发生变化。它永远不会和原来的一样。litteral 的属性按字母顺序排序(只有危险?)。
This would not be a problem if both solutions did not behave differently when I try to transform them. I picked up some intresting Code from Daniel C. Sobral at How to change attribute on Scala XML Elementand wrote my own rule in order to remove the first slash of the "href" attribute. The RuleTransformer works well with the in_xml, but has no effect on from_str !
如果当我尝试转换它们时两种解决方案的行为没有不同,这将不是问题。我从 Daniel C. Sobral 在How to change attribute on Scala XML Element 中挑选了一些有趣的代码,并编写了我自己的规则以删除“href”属性的第一个斜杠。RuleTransformer 与 in_xml 配合良好,但对 from_str 没有影响!
Unfortunately, most of my programs have to read there XML via XML.load(...). So, I'm stuck. Does someone know about this topic ?
不幸的是,我的大多数程序都必须通过 XML.load(...) 读取 XML。所以,我被困住了。有人知道这个话题吗?
Best regards,
最好的祝福,
Henri
亨利
回答by huynhjl
From what I can see, in_xmland from_strare 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:
从我所看到的,in_xml而from_str不是等于,因为属性的顺序是不同的。这是不幸的,并且由于编译器创建 XML 的方式。这导致属性不同:
scala> in_xml.attributes == from_str.attributes
res30: 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_str
res32: Boolean = true
With that said, I'm not clear why that would cause a different behavior in the code that replaces the hrefattribute. In fact I suspect that something is wrong with the way attribute mapping works. For instance, if I replace the in_strwith:
话虽如此,我不清楚为什么这会在替换href属性的代码中导致不同的行为。事实上,我怀疑属性映射的工作方式有问题。例如,如果我替换为in_str:
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?
它工作正常。难道 Daniel 的属性代码只有在属性位于 的头部位置时才有效MetaData?
Side note: unless in_xmlis null, equalsand ==would return the same value. The ==version will check whether the first operand is null before calling equals.
旁注:除非in_xml是null,equals并且==会返回相同的值。该==版本将检查第一个操作数是否为空之前调用equals。
回答by Henri Bauer
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
也就是说,如果我在 REPL 中测试以下内容
<body id="1234"></body> == XML.loadString("<body id=\"1234\"></body>")
I get true, even without calling the equals method...
我是真的,即使没有调用 equals 方法......
Back to my initial example: I defined a rewrite rule
回到我最初的例子:我定义了一个重写规则
def unSlash(s: String) = if (s.head == '/') s.tail else s
val 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:
它使用 Daniel C. Sobral 在How to change attribute on Scala XML Element 中定义的辅助类/方法。如果我申请:
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...
我用 in_xml 得到了预期的结果,但没有用 from_str 修改...

