package org.itsnat.droid.impl.dommini; import org.itsnat.droid.ItsNatDroidException; import org.itsnat.droid.impl.util.MiscUtil; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; /** * Created by jmarranz on 10/02/2016. */ public class DOMMiniParser { public static DMNode[] parse(XmlPullParser parser) throws IOException, XmlPullParserException { // Se espera que parser esté inicialmente en START_TAG if (parser.getEventType() != XmlPullParser.START_TAG) throw MiscUtil.internalError(); ArrayList<DMNode> nodeList = new ArrayList<DMNode>(); while(parser.nextToken() != XmlPullParser.END_TAG) { if (isIgnored(parser.getEventType())) continue; DMNode nextSibling = processNextSiblingToken(parser); nodeList.add(nextSibling); } DMNode[] nodeArray = nodeList.toArray(new DMNode[nodeList.size()]); return nodeArray; } private static DMNode processNextSiblingToken(XmlPullParser parser) throws IOException, XmlPullParserException { int tokenType = parser.getEventType(); if (tokenType == XmlPullParser.START_TAG) { return processElement(parser); } else if (tokenType == XmlPullParser.TEXT) { return processTextNode(parser); } else if (tokenType == XmlPullParser.CDSECT) { return processCDSECT(parser); } else if (tokenType == XmlPullParser.ENTITY_REF) { return processEntity(parser); } throw new ItsNatDroidException("Unexpected token " + tokenType); } private static DMEntityRefNode processEntity(XmlPullParser parser) throws IOException, XmlPullParserException { int tokenType = parser.getEventType(); if (tokenType != XmlPullParser.ENTITY_REF) throw MiscUtil.internalError(); // parser.getText() devuelve el entity resuelto, ej "<" => "<" PERO no nos interesa, pues luego Html.fromHtml lo hará // En teoría parser.getTextCharacters(new int[2]) debería devolvernos el entity sin resolver pero NO es así // Afortunadamente he descubierto que getName() devuelve el entity sin & ni ; es decir por ejemplo "lt" String entityName = parser.getName(); String resolvedEntity = parser.getText(); return new DMEntityRefNode(entityName,resolvedEntity); } private static DMTextNode processTextNode(XmlPullParser parser) throws IOException, XmlPullParserException { int tokenType = parser.getEventType(); if (tokenType != XmlPullParser.TEXT && tokenType != XmlPullParser.CDSECT) throw MiscUtil.internalError(); return new DMTextNode(parser.getText()); } private static DMCDSECTNode processCDSECT(XmlPullParser parser) throws IOException, XmlPullParserException { int tokenType = parser.getEventType(); if (tokenType != XmlPullParser.CDSECT) throw MiscUtil.internalError(); return new DMCDSECTNode(parser.getText()); } private static DMElem processElement(XmlPullParser parser) throws IOException, XmlPullParserException { if (parser.getEventType() != XmlPullParser.START_TAG) throw MiscUtil.internalError(); DMElem elem = new DMElem(parser.getName()); int attrLen = parser.getAttributeCount(); for(int i = 0; i < attrLen; i++) { String name = parser.getAttributeName(i); String value = parser.getAttributeValue(i); DMAttr attr = new DMAttr(name,value); elem.addDMAttr(attr); } processChildNodes(parser,elem); return elem; } private static void processChildNodes(XmlPullParser parser,DMElem elem) throws IOException, XmlPullParserException { while(parser.nextToken() != XmlPullParser.END_TAG) { if (isIgnored(parser.getEventType())) continue; DMNode nextChild = processNextSiblingToken(parser); elem.addChildDMNode(nextChild); } } private static boolean isIgnored(int tokenType) { return tokenType == XmlPullParser.COMMENT; } }