#xml #scala #stream #xmlstreamreader
#xml #scala #поток #xmlstreamreader
Вопрос:
На самом деле я перестраиваю существующее большое программное обеспечение и переключаюсь с XMLEventReader
XMLStreamReader
на в целях экономии памяти.
Рассмотрим следующее определение функции, которая в настоящее время просто считывает XML-событие и печатает их:
def evalStreamReader(source: StreamSource): Unit
val StreamReader = XMLInputFactory.newInstance().createXMLStreamReader(source)
while (StreamReader.hasNext) {
val eventType = StreamReader.getEventType
eventType match {
case 1 => println("Start Element " eventType " : " StreamReader.getLocalName)
case 2 => println("End Element " eventType " : " StreamReader.getLocalName)
case 4 => println("Characters " eventType " : " StreamReader.getText)
case 7 => println("Start Document " eventType)
case 8 => println("End Document: " eventType)
}
StreamReader.next()
}
}
и простой XML-файл :
<a>
<c></c>
</a>
Вывод будет :
Start Document 7
Start Element 1 : a
Characters 4 :
Start Element 1 : c
End Element 2 : c
Characters 4 :
End Element 2 : a
Могу ли я в любом случае обработать событие END_DOCUMENT
отдельно / правильно в While
соответствии с условием / регистром, а не вне цикла? Я перепробовал много условий, do while
но безуспешно.
Идея заключается в том, что StreamReader.next()
курсор переключит END_DOCUMENT
событие и hasNext
вернет false по его определению в API:
boolean hasNext()
throws XMLStreamException
Returns true if there are more parsing events and false if there are no more events.
This method will return false if the current state of the XMLStreamReader is END_DOCUMENT
Комментарии:
1. Но в чем ваша проблема, которая не позволяет вам сделать то, что вы хотите? Код для конечного документа никогда не вызывается, когда внутри while?
Ответ №1:
Пример наивного неидиоматического подхода:
def evalStreamReader(source: StreamSource): Unit = {
val streamReader: XMLStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(source)
var finished: Boolean = false
do {
val eventType = streamReader.getEventType
if (eventType != 8) {
eventType match {
case 1 => println("Start Element " eventType " : " streamReader.getLocalName)
case 2 => println("End Element " eventType " : " streamReader.getLocalName)
case 4 => println("Characters " eventType " : " streamReader.getText)
case 7 => println("Start Document " eventType)
}
streamReader.next()
} else {
println("End Document: " eventType)
finished = true
}
} while(!finished)
streamReader.close()
}
Это привело бы к:
Start Document 7
Start Element 1 : a
Characters 4 :
Start Element 1 : c
End Element 2 : c
Characters 4 :
End Element 2 : a
End Document: 8
по сути, вам нужно отделить управление потоком от считывателя.