2010-12-09 6 views
8

저는 스칼라와 XML을 실험 해본 결과 XML.load (또는 loadString)로 만든 XML 태그와 리터럴로 쓰는 XML 태그 사이에 이상한 차이가 있음을 발견했습니다. 여기스칼라 XML.loadString 대 리터럴 표현

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())) 

그리고, 출력 :

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 

유형이 동일 여기에 코드입니다. 그러나 평등은 없습니다. 속성의 순서가 변경됩니다. 그것은 원래의 것과 결코 같지 않습니다. litteral의 속성은 사전 순으로 정렬됩니다 (위험 요소 만 해당).

변환 할 때 두 솔루션이 다르게 동작하지 않으면 문제가되지 않습니다. 나는 Daniel C. Sobral로부터 intresting Code를 How to change attribute on Scala XML Element에 가져 왔고 "href"속성의 첫 번째 슬래시를 제거하기 위해 내 자신의 규칙을 썼다. RuleTransformer는 in_xml과 잘 작동하지만 from_str에는 영향을주지 않습니다!

불행히도, 대부분의 프로그램은 XML.load (...)를 통해 XML을 읽어야합니다. 그래서, 나는 붙어있다. 누군가이 주제에 대해 알고 있습니까?

안부,

앙리

+1

이것은 분명히 버그입니다. ... –

+0

스칼라 XML 리터럴은 속성 순서에 대한 문제점을 알고 있습니다. http://lampsvn.epfl.ch/trac/scala/ticket/2735에 대한 찬성 투표를 할 수 있습니다. (실제로 투표에주의를 기울이는 지 모르지만 상처를 입을 수는 없습니다.) – Steve

+0

그들은 투표에주의를 기울이지 않지만 활동 (사람들은 구독하고 의견을 말하기 등)에주의를 기울입니다. 그래도 상처를주지 않습니다. 나는 개인적으로 내가 관심있는 버그를 구독하고 특히 중요하다고 생각하는 것을 upvote한다. –

답변

0

일부 추가 시험 :

in_xml == from_str 

내가 테스트하는 경우 : 아마, 내 초기 평등 테스트는 적합하지 않다

in_xml.equals(in_xml) 

나는 또한 거짓을 얻습니다. 어쩌면, 나는 또 다른 시험 방법을 사용해야합니다 (대응처럼,하지만 난 알아하지 않았다 내가이 두 번째 매개 변수로 사용해야합니다 술어 ...) 내가 테스트를 경우하여 REPL에서 다음 말했다

<body id="1234"></body> == XML.loadString("<body id=\"1234\"></body>") 

심지어 equals 메소드를 호출하지 않고, 진정한 얻을 수는 ...

다시 내 최초의 예 : 나는 재 작성 규칙이 헬퍼 클래스/메소드를 사용

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 
    } 
} 

정의 Daniel C. Sobral에 의해 정의 된 How to change attribute on Scala XML Element. 내가 적용하는 경우 :

new RuleTransformer(changeCSS).transform(in_xml) 
new RuleTransformer(removeComments).transform(from_str) 

을 나는 in_xml와 예상 결과를 얻을 수 있지만, from_str 아무런 수정 ...

1
내가 무엇을 볼 수에서

, in_xmlfrom_str은 속성의 순서가 있기 때문에하지가 동일하지 않습니다 다른. 이것은 불행한 일이며 컴파일러가 XML을 작성하는 방식 때문에 발생합니다.그 원인이 이유가 명확하지 않다, 말했다와

scala> in_xml.copy(attributes=from_str.attributes) == from_str 
res32: Boolean = true 

을 : 당신이 속성을 대체 할 경우 비교가 작동한다고 볼

scala> in_xml.attributes == from_str.attributes 
res30: Boolean = false 

당신은 볼 수 있습니다 : 그것은 다를 수 속성을 발생 href 특성을 대체하는 코드의 다른 동작 사실 나는 속성 매핑이 작동하는 방식에 문제가 있다고 의심합니다. 예를 들어 in_str을 다음으로 대체하면 :

val in_str = """<link type="text/css" rel="stylesheet" href="/css/main.css" 
xmlns="http://www.w3.org/1999/xhtml"></link>""" 

잘 작동합니다. Daniel의 속성 코드가 속성이 머리 위치 인 MetaData에있는 경우에만 작동 할 수 있습니까?


사이드 참고 : in_xml가 아닌 null, equals==가 같은 값을 반환합니다. == 버전은 equals을 호출하기 전에 첫 번째 피연산자가 null인지 확인합니다.