どうすればいいのかわからなかったのですが、パンゲア が道を教えてくれました。まず、場所を処理するためのトレイトを作成しましょう。
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
にほとんど追加しません。完全に置き換える必要があると感じた場合は、そのソースコードを確認することをお勧めします。しかし、これは、Scalaにはすでにエラーを生成する特性があるため、これらすべてを自分で処理したい場合にのみ発生します。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
このスタックからvar
使用者にポップするようにオーバーライドすることで改善できることの1つですcreateNode
。
いい質問です。私は多くのことを学びました!:-)