/******************************************************************************* * Copyright 2012 Crazywater * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package de.knufficast.logic; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.HashMap; import java.util.Map; import java.util.Stack; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; public abstract class XmlParser { private String encoding; private Stack<String> currentTags; /** * Parses an XML input. Resulting feeds can be retrieved with * {@link #getFeeds}. * * @param xml * the input stream of XML data * @param feedUrl * the URL to set as feedUrl (used for identification purposes) * @param timestamp * the timestamp when the feed was downloaded * @param eTag * the eTag header the server delivers. Can be used for caching * purposes, can also be null. * @throws XmlPullParserException * for malformed XML * @throws IOException * for connection problems */ protected void parseFrom(InputStream xml) throws XmlPullParserException, IOException { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); xpp.setInput(xml, null); doParse(xpp); } protected void parseFrom(Reader xml) throws XmlPullParserException, IOException { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); xpp.setInput(xml); doParse(xpp); } private void doParse(XmlPullParser xpp) throws XmlPullParserException, IOException { currentTags = new Stack<String>(); int eventType = xpp.getEventType(); try { encoding = xpp.getInputEncoding(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { Map<String, String> attributes = new HashMap<String, String>(); for (int i = 0; i < xpp.getAttributeCount(); i++) { attributes.put(xpp.getAttributeName(i).toLowerCase(), xpp.getAttributeValue(i)); } String tagName = xpp.getName().toLowerCase(); onOpenTag(tagName); openTag(tagName, attributes); } else if (eventType == XmlPullParser.END_TAG) { String expected = currentTags.peek(); String got = xpp.getName().toLowerCase(); if (!expected.equals(got)) { throw new XmlPullParserException("Malformed XML: Closing tag " + got + ", expected closing " + expected); } onCloseTag(got); closeTag(got); } else if (eventType == XmlPullParser.TEXT) { onTagText(xpp.getText()); tagText(xpp.getText()); } eventType = xpp.next(); } } catch (NullPointerException e) { e.printStackTrace(); throw new XmlPullParserException("Malformed XML: " + e.getMessage()); } } protected String getEncoding() { return encoding; } protected abstract void openTag(String tag, Map<String, String> attributes); protected abstract void closeTag(String tag); protected abstract void tagText(String text); private void onOpenTag(String tag) { currentTags.push(tag); } private void onCloseTag(String tag) { currentTags.pop(); } private void onTagText(String text) { } protected String getCurrentTag() { return currentTags.peek(); } protected String getParentTag() { String current = currentTags.pop(); String parent = currentTags.peek(); currentTags.push(current); return parent; } }