package com.mappn.gfan.common.util; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.http.protocol.HTTP; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; public class XmlElement { private String name; private Map<String, Object> attributes; private List<String> text; private Map<String, List<XmlElement>> children; private List<XmlElement> childrenList; private List<Object> all; private static final String TAG_LEFT = "<"; private static final String TAG_RIGHT = ">"; private static final String TAG_END = "/"; private static final String EQUEL = "="; private static final String QUOT = "\""; private static final String SPACE = " "; private static final String[] REPLACE = { "&", "&", "\"", """, "'", "'", "<", "<", ">", ">" }; private static final int REPLACE_LENGTH = REPLACE.length % 2 == 0 ? REPLACE.length : REPLACE.length - 1; public XmlElement(String name) { this.name = name; attributes = new LinkedHashMap<String, Object>(); text = new ArrayList<String>(10); children = new LinkedHashMap<String, List<XmlElement>>(); childrenList = new ArrayList<XmlElement>(30); all = new ArrayList<Object>(100); } public String getName() { return name; } public Map<String, Object> getAttributes() { return attributes; } public String getAttribute(String name) { return (String)attributes.get(name); } public XmlElement addAttributes(Map<String, String> attributes) { if (attributes != null) { this.attributes.putAll(attributes); } return this; } public XmlElement setAttribute(String name, String value) { this.attributes.put(name, value); return this; } public List<String> getAllText() { return text; } public String getText(int index) { return text.size() > index ? text.get(index) : ""; } public String getText() { return getText(0); } public XmlElement addText(String text) { this.text.add(text); this.all.add(text); return this; } public List<XmlElement> getAllChildren() { return childrenList; } public List<XmlElement> getChildren(String tagName) { return children.get(tagName); } public XmlElement getChild(String tagName, int index) { List<XmlElement> children = getChildren(tagName); return children != null && children.size() > index ? children .get(index) : null; } public XmlElement getChild(int index) { return childrenList.size() > index ? childrenList.get(index) : null; } public XmlElement addChild(XmlElement child) { if (child != null && child.name != null) { childrenList.add(child); all.add(child); if (!children.containsKey(child.name)) { children.put(child.name, new ArrayList<XmlElement>(10)); } children.get(child.name).add(child); } return this; } public XmlElement addChildren(List<XmlElement> children) { if (children != null) { for (XmlElement element : children) { addChild(element); } } return this; } public List<Object> getAllTextAndChildren() { return all; } public XmlElement clear() { attributes.clear(); text.clear(); children.clear(); childrenList.clear(); all.clear(); return this; } public static XmlElement parseXml(InputStream in) throws XmlPullParserException, IOException { if (in == null) { return null; } XmlElement result = null; XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); xpp.setInput(in, HTTP.UTF_8); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { result = new XmlElement(xpp.getName()); result.parseXml(xpp); } else { try { if (eventType != XmlPullParser.START_DOCUMENT) { Utils.W(XmlPullParser.TYPES[eventType]); } } catch (Throwable t) { Utils.E("Oh! My God!", t); } } eventType = xpp.next(); } return result; } public void writeAsXml(Writer writer) throws IOException { addXml(writer, this); } public String toString() { StringWriter sw = new StringWriter(); try { writeAsXml(sw); } catch (IOException e) { Utils.E("Oh! My God!", e); } return sw.toString(); } private void parseXml(XmlPullParser xpp) throws XmlPullParserException, IOException { for (int i = 0; i < xpp.getAttributeCount(); i++) { setAttribute(xpp.getAttributeName(i), xpp.getAttributeValue(i)); } int eventType = xpp.next(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { XmlElement child = new XmlElement(xpp.getName()); addChild(child); child.parseXml(xpp); } if (eventType == XmlPullParser.END_TAG) { return; } if (eventType == XmlPullParser.TEXT) { addText(xpp.getText()); } eventType = xpp.next(); } } private void addXml(Writer sb, XmlElement element) throws IOException { if (element.all.size() == 0) { element.addTag(sb); } else { element.addTagStart(sb); for (Object item : element.all) { if (item != null) { if (item instanceof String) { element.addText(sb, (String) item); } else { element.addXml(sb, (XmlElement) item); } } } element.addTagEnd(sb); } } private void addTagStart(Writer sb) throws IOException { sb.append(TAG_LEFT).append(name); addAttributes(sb); sb.append(TAG_RIGHT); } private void addTagEnd(Writer sb) throws IOException { sb.append(TAG_LEFT).append(TAG_END).append(name).append(TAG_RIGHT); } private void addTag(Writer sb) throws IOException { sb.append(TAG_LEFT).append(name); addAttributes(sb); sb.append(SPACE).append(TAG_END).append(TAG_RIGHT); } private void addAttributes(Writer sb) throws IOException { if (attributes != null) { for (Map.Entry<String, Object> item : attributes.entrySet()) { sb.append(SPACE).append(item.getKey()).append(EQUEL).append( QUOT); addText(sb, (String)item.getValue()); sb.append(QUOT); } } } private void addText(Writer sb, String text) throws IOException { if (text != null) { for (int i = 0; i < REPLACE_LENGTH; i += 2) { text = text.replace(REPLACE[i], REPLACE[i + 1]); } sb.append(text); } } }