Поскольку вопрос старый, вероятно, проблема больше не существует, но я просто пытался сделать то же самое.Пример кода был почти там;отсутствующим шагом была проверка типа события XMLStreamConstants.CHARACTERS
, который соответствует либо:
- данных между открывающим и закрывающим тегом.
- Пробел между тегами.
Таким образом, в вашем случае вы хотите извлечь данные только при соблюдении всех этих условий:
- Тип обрабатываемого события:
XMLStreamConstants.CHARACTERS
(в этом случае EventType.isCharacters()
возвращает истину). - Обработанное непосредственно предшествующее событие имело тип
XMLStreamConstants.START_ELEMENT
. - Значением атрибута type этого предшествующего начального элемента было "id2" или "id3".
Это можно сделать путем настройки существующего кода, но более чистый и более общий подход состоит в том, чтобы итеративно обрабатывать события, возвращаемые XMLEventReader
, с помощью оператора case
.Чтобы получить значение данных между начальным тегом и конечным тегом:
Characters characters = xmlEvent.asCharacters();
String data = characters.getData();
Вот рабочий пример, где файл sample.xml содержит данные в OP:
package pkg;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
public class StaxDemo {
public static void main(String[] args) throws XMLStreamException, IOException {
try (Reader reader = new FileReader("sample.xml");) {
XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(reader);
parseXml(xmlEventReader);
}
}
static void parseXml(XMLEventReader xmlEventReader) throws XMLStreamException {
String typeValue = null;
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = xmlEventReader.nextEvent();
switch (xmlEvent.getEventType()) {
case XMLStreamConstants.START_DOCUMENT:
System.out.println("XMLEvent.START_DOCUMENT");
break;
case XMLStreamConstants.START_ELEMENT:
StartElement startElement = xmlEvent.asStartElement();
Attribute typeAttribute = startElement.getAttributeByName(new QName("type"));
if (typeAttribute != null) {
typeValue = typeAttribute.getValue();
}
System.out.println("XMLEvent.START_ELEMENT: <" + startElement.getName() + "> " + "type=" + typeValue);
break;
case XMLStreamConstants.CHARACTERS:
Characters characters = xmlEvent.asCharacters();
if ((typeValue != null)) { // Non-null if preceding event was for START_ELEMENT.
if ((typeValue.equals("id2")) || (typeValue.equals("id3"))) {
String data = characters.getData();
System.out.println("XMLEvent.CHARACTERS: data=[" + data + "]");
}
typeValue = null;
}
break;
case XMLStreamConstants.END_ELEMENT:
EndElement endElement = xmlEvent.asEndElement();
System.out.println("XMLEvent.END_ELEMENT: </" + endElement.getName() + ">");
break;
case XMLStreamConstants.END_DOCUMENT:
System.out.println("XMLEvent.END_DOCUMENT");
break;
default:
System.out.println("case default: Event Type = " + xmlEvent.getEventType());
break;
}
}
}
}
Я добавил несколько вызовов println()
, чтобы просто уточнить, как файл обрабатывается XMLEventReader
.Вот вывод:
XMLEvent.START_DOCUMENT
XMLEvent.START_ELEMENT: <entity> type=null
XMLEvent.START_ELEMENT: <id> type=id1
XMLEvent.END_ELEMENT: </id>
XMLEvent.START_ELEMENT: <id> type=id2
XMLEvent.CHARACTERS: data=[z8500124]
XMLEvent.END_ELEMENT: </id>
XMLEvent.START_ELEMENT: <id> type=id3
XMLEvent.CHARACTERS: data=[z8500125]
XMLEvent.END_ELEMENT: </id>
XMLEvent.START_ELEMENT: <link> type=null
XMLEvent.END_ELEMENT: </link>
XMLEvent.END_ELEMENT: </entity>
XMLEvent.END_DOCUMENT
Oracle предоставляет учебник для StAX .Пока есть вся основная информация, я нашел ее немного неорганизованной.