我不知道該怎麼做,但Pangeashowed me the way。首先,讓我們創建一個特徵來處理地點:
import org.xml.sax.{helpers, Locator, SAXParseException}
trait WithLocation extends helpers.DefaultHandler {
var locator: org.xml.sax.Locator = _
def printLocation(msg: String) {
println("%s at line %d, column %d" format (msg, locator.getLineNumber, locator.getColumnNumber))
}
// Get location
abstract override def setDocumentLocator(locator: Locator) {
this.locator = locator
super.setDocumentLocator(locator)
}
// Display location messages
abstract override def warning(e: SAXParseException) {
printLocation("warning")
super.warning(e)
}
abstract override def error(e: SAXParseException) {
printLocation("error")
super.error(e)
}
abstract override def fatalError(e: SAXParseException) {
printLocation("fatal error")
super.fatalError(e)
}
}
接下來,讓我們來創建自己的裝載機覆蓋XMLLoader
的adapter
,包括我們的特點:
import scala.xml.{factory, parsing, Elem}
object MyLoader extends factory.XMLLoader[Elem] {
override def adapter = new parsing.NoBindingFactoryAdapter with WithLocation
}
而這一切就是這麼簡單!對象XML
幾乎沒有添加到XMLLoader
- 基本上,save
方法。如果您覺得需要全面更換,您可能需要查看其源代碼。但這只是如果你想處理這一切的自己,因爲斯卡拉已經有一個特點產生錯誤:
object MyLoader extends factory.XMLLoader[Elem] {
override def adapter = new parsing.NoBindingFactoryAdapter with parsing.ConsoleErrorHandler
}
的ConsoleErrorHandler
特點,從異常提取其行和數量的信息,順便說一句。對於我們的目的,我們需要的地點也是例外(我假設)。
現在,修改節點創作本身,看看scala.xml.factory.FactoryAdapter
抽象方法。我已經看中了createNode
,但我在NoBindingFactoryAdapter
水平壓倒一切,因爲它返回Elem
代替Node
,使我添加屬性。所以:
import org.xml.sax.Locator
import scala.xml._
import parsing.NoBindingFactoryAdapter
trait WithLocation extends NoBindingFactoryAdapter {
var locator: org.xml.sax.Locator = _
// Get location
abstract override def setDocumentLocator(locator: Locator) {
this.locator = locator
super.setDocumentLocator(locator)
}
abstract override def createNode(pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, children: List[Node]): Elem = (
super.createNode(pre, label, attrs, scope, children)
% Attribute("line", Text(locator.getLineNumber.toString), Null)
% Attribute("column", Text(locator.getColumnNumber.toString), Null)
)
}
object MyLoader extends factory.XMLLoader[Elem] {
// Keeping ConsoleErrorHandler for good measure
override def adapter = new parsing.NoBindingFactoryAdapter with parsing.ConsoleErrorHandler with WithLocation
}
結果:
scala> MyLoader.loadString("<a><b/></a>")
res4: scala.xml.Elem = <a line="1" column="12"><b line="1" column="8"></b></a>
注意,它拿到了最後一個位置,一個在結束標記。這是一兩件事,可以通過覆蓋startElement
跟蹤,其中每個元素在堆棧中開始得到改善,endElement
從這個堆棧彈出成createNode
使用的var
。
有趣的問題。我學到了很多! :-)
抱歉回答這麼晚。你的答案很棒。我沒有想到一個真正的解決方案,但你實際上找到了一個。非常感謝! – Madoc 2010-12-31 11:56:39
現在,如果只有你或某人能夠顯示如何獲得起始行號:P – Jus12 2014-01-27 09:11:19