Вы делаете распространенную ошибку, предполагая, что метод characters
будет вызываться только один раз между парой вызовов startElement
и endElement
из анализатора и предоставит содержимое entore между начальным и конечным тегами.На самом деле его можно вызывать много раз, и каждый вызов содержит только часть содержимого.
Надлежащая обработка заключается в создании или подключении аккумулятора некоторого вида (обычно StringBuilder
или StringBuffer
) вМетод startElement, накапливается в нем в методе символов, а затем используется и удаляется или отключается в методе endElement.
Я думаю, что в вашем коде есть кое-что неправильное, но это может послужить началом его работы.
Чтобы обрабатывать только элементы внутри определенного тега, выхотите установить логический флаг, означающий, что вы нашли его в методе startElement
при просмотре этого тега, установите для него значение false в endElement для тега и проверьте этот флаг перед сбором данных из любых других тегов.Вам нужно будет использовать описанный выше процесс для каждого из вложенных тегов с <item>
, поскольку они содержат свои данные в виде символов.
Для моего собственного удовольствия и в надежде, что это может помочь вам понять все этоЧуть лучше, я написал небольшой обработчик, который собирает данные под <temperaturetags>
в список карт.
package com.donroby;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WeatherHandler extends DefaultHandler {
private List<Map<String,String>> result = new ArrayList<Map<String,String>>();
private Map<String,String> currentItem;
private boolean collectingItems;
private boolean collectingItem;
private StringBuilder builder;
public List<Map<String,String>> getResult() {
return result;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals("temperaturetags")) {
collectingItems = true;
}
else if (qName.equals("item") && collectingItems) {
currentItem = new HashMap<String,String>();
currentItem.put("name", attributes.getValue("name"));
collectingItem = true;
}
else if (collectingItem) {
builder = new StringBuilder();
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("temperaturetags")) {
collectingItems = false;
}
if (qName.equals("item") && collectingItems) {
result.add(currentItem);
currentItem = null;
collectingItem = false;
}
else if (collectingItem) {
currentItem.put(qName, builder.toString());
builder = null;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (collectingItem &&(builder != null)) {
builder.append(ch, start, length);
}
}
}
Для реального использования я бы с большей вероятностью создал объект домена и собрал всписок этого класса, но это приведет к тому, что код будет немного больше, чем я хотел бы сделать для быстрого примера.