XMLStream Reader Scala — надлежащий дескриптор END_DOCUMENT

#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
  

по сути, вам нужно отделить управление потоком от считывателя.