implement standard XmlPullParser & android s XmlResourceParser #18

This commit is contained in:
REAndroid 2023-03-26 16:00:30 -04:00
parent ebd8cec757
commit cd481f2e19
20 changed files with 3379 additions and 16 deletions

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* 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 android.content.res;
import android.util.AttributeSet;
import org.xmlpull.v1.XmlPullParser;
public interface XmlResourceParser extends XmlPullParser, AttributeSet, AutoCloseable {
String getAttributeNamespace (int index);
public void close();
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* 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 android.util;
public interface AttributeSet {
public int getAttributeCount();
default String getAttributeNamespace (int index) {
return null;
}
public String getAttributeName(int index);
public String getAttributeValue(int index);
public String getAttributeValue(String namespace, String name);
public String getPositionDescription();
public int getAttributeNameResource(int index);
public int getAttributeListValue(String namespace, String attribute, String[] options, int defaultValue);
public boolean getAttributeBooleanValue(String namespace, String attribute, boolean defaultValue);
public int getAttributeResourceValue(String namespace, String attribute, int defaultValue);
public int getAttributeIntValue(String namespace, String attribute, int defaultValue);
public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue);
public float getAttributeFloatValue(String namespace, String attribute, float defaultValue);
public int getAttributeListValue(int index, String[] options, int defaultValue);
public boolean getAttributeBooleanValue(int index, boolean defaultValue);
public int getAttributeResourceValue(int index, int defaultValue);
public int getAttributeIntValue(int index, int defaultValue);
public int getAttributeUnsignedIntValue(int index, int defaultValue);
public float getAttributeFloatValue(int index, float defaultValue);
public String getIdAttribute();
public String getClassAttribute();
public int getIdAttributeResourceValue(int defaultValue);
public int getStyleAttribute();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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 com.android.org.kxml2.io;
// Taken from libcore.internal.StringPool
class LibCoreStringPool {
private final String[] pool = new String[512];
public LibCoreStringPool() {
}
private static boolean contentEquals(String s, char[] chars, int start, int length) {
if (s.length() != length) {
return false;
}
for (int i = 0; i < length; i++) {
if (chars[start + i] != s.charAt(i)) {
return false;
}
}
return true;
}
/**
* Returns a string equal to {@code new String(array, start, length)}.
*/
public String get(char[] array, int start, int length) {
// Compute an arbitrary hash of the content
int hashCode = 0;
for (int i = start; i < start + length; i++) {
hashCode = (hashCode * 31) + array[i];
}
// Pick a bucket using Doug Lea's supplemental secondaryHash function (from HashMap)
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
hashCode ^= (hashCode >>> 7) ^ (hashCode >>> 4);
int index = hashCode & (pool.length - 1);
String pooled = pool[index];
if (pooled != null && contentEquals(pooled, array, start, length)) {
return pooled;
}
String result = new String(array, start, length);
pool[index] = result;
return result;
}
}

View File

@ -110,6 +110,8 @@ public class XMLFileEncoder {
entry =getAttributeBlock(attribute); entry =getAttributeBlock(attribute);
if(entry !=null){ if(entry !=null){
resourceId= entry.getResourceId(); resourceId= entry.getResourceId();
}else if(attribute.getNamePrefix()!=null){
throw new EncodeException("No resource found for: "+attribute.getName()+": "+mCurrentPath);
} }
} }
ResXmlAttribute xmlAttribute = ResXmlAttribute xmlAttribute =

View File

@ -75,7 +75,7 @@
} }
return startNamespace.getPrefix(); return startNamespace.getPrefix();
} }
@Deprecated // WARN! Careful this is not real value
public String getValueString(){ public String getValueString(){
return getString(getValueStringReference()); return getString(getValueStringReference());
} }

View File

@ -39,7 +39,7 @@
private final BlockList<ResXmlNode> mBody; private final BlockList<ResXmlNode> mBody;
private final SingleBlockContainer<ResXmlEndElement> mEndElementContainer; private final SingleBlockContainer<ResXmlEndElement> mEndElementContainer;
private final BlockList<ResXmlEndNamespace> mEndNamespaceList; private final BlockList<ResXmlEndNamespace> mEndNamespaceList;
private int mDepth; private int mLevel;
public ResXmlElement() { public ResXmlElement() {
super(5); super(5);
this.mStartNamespaceList = new BlockList<>(); this.mStartNamespaceList = new BlockList<>();
@ -103,6 +103,7 @@
} }
} }
} }
@Override
public String getComment(){ public String getComment(){
return getStartElement().getComment(); return getStartElement().getComment();
} }
@ -282,6 +283,20 @@
} }
return null; return null;
} }
public int getAttributeCount() {
ResXmlStartElement startElement=getStartElement();
if(startElement!=null){
return startElement.getResXmlAttributeArray().childesCount();
}
return 0;
}
public ResXmlAttribute getAttributeAt(int index){
ResXmlStartElement startElement=getStartElement();
if(startElement!=null){
return startElement.getResXmlAttributeArray().get(index);
}
return null;
}
public Collection<ResXmlAttribute> listAttributes(){ public Collection<ResXmlAttribute> listAttributes(){
ResXmlStartElement startElement=getStartElement(); ResXmlStartElement startElement=getStartElement();
if(startElement!=null){ if(startElement!=null){
@ -313,11 +328,21 @@
return getParentInstance(ResXmlDocument.class); return getParentInstance(ResXmlDocument.class);
} }
@Override
public int getDepth(){ public int getDepth(){
return mDepth; int depth = 0;
ResXmlElement parent = getParentResXmlElement();
while (parent!=null){
depth++;
parent = parent.getParentResXmlElement();
} }
private void setDepth(int depth){ return depth;
mDepth=depth; }
public int getLevel(){
return mLevel;
}
private void setLevel(int level){
mLevel = level;
} }
public void addElement(ResXmlElement element){ public void addElement(ResXmlElement element){
mBody.add(element); mBody.add(element);
@ -359,6 +384,12 @@
mBody.remove(xmlNode); mBody.remove(xmlNode);
} }
} }
public ResXmlNode getResXmlNode(int position){
return mBody.get(position);
}
public int countResXmlNodes(){
return mBody.size();
}
public List<ResXmlNode> listXmlNodes(){ public List<ResXmlNode> listXmlNodes(){
return new ArrayList<>(getXmlNodes()); return new ArrayList<>(getXmlNodes());
} }
@ -412,14 +443,7 @@
return this; return this;
} }
public ResXmlElement getParentResXmlElement(){ public ResXmlElement getParentResXmlElement(){
Block parent=getParent(); return getParentInstance(ResXmlElement.class);
while (parent!=null){
if(parent instanceof ResXmlElement){
return (ResXmlElement)parent;
}
parent=parent.getParent();
}
return null;
} }
public ResXmlStartNamespace getStartNamespaceByUriRef(int uriRef){ public ResXmlStartNamespace getStartNamespaceByUriRef(int uriRef){
if(uriRef<0){ if(uriRef<0){
@ -669,7 +693,7 @@
} }
private void onFinishedRead(BlockReader reader, HeaderBlock headerBlock) throws IOException{ private void onFinishedRead(BlockReader reader, HeaderBlock headerBlock) throws IOException{
int avail=reader.available(); int avail=reader.available();
if(avail>0 && getDepth()==0){ if(avail>0 && getLevel()==0){
onFinishedUnexpected(reader); onFinishedUnexpected(reader);
return; return;
} }
@ -692,7 +716,7 @@
if(hasStartElement()){ if(hasStartElement()){
ResXmlElement childElement=new ResXmlElement(); ResXmlElement childElement=new ResXmlElement();
addElement(childElement); addElement(childElement);
childElement.setDepth(getDepth()+1); childElement.setLevel(getLevel()+1);
childElement.readBytes(reader); childElement.readBytes(reader);
}else{ }else{
ResXmlStartElement startElement=new ResXmlStartElement(); ResXmlStartElement startElement=new ResXmlStartElement();

View File

@ -25,6 +25,8 @@ public abstract class ResXmlNode extends FixedBlockContainer implements JSONCon
} }
void onRemove(){ void onRemove(){
} }
public abstract String getComment();
public abstract int getDepth();
public static final String NAME_node_type="node_type"; public static final String NAME_node_type="node_type";
} }

View File

@ -0,0 +1,700 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* 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 com.reandroid.arsc.chunk.xml;
import android.content.res.XmlResourceParser;
import com.reandroid.arsc.value.ValueType;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class ResXmlPullParser implements XmlResourceParser {
private ResXmlDocument mDocument;
private boolean mDocumentCreatedHere;
private ResXmlElement mCurrentElement;
private ResXmlTextNode mCurrentText;
private int mEvent = -1;
public ResXmlPullParser(){
}
public void setResXmlDocument(ResXmlDocument xmlDocument){
closeDocument();
this.mDocument = xmlDocument;
}
public ResXmlDocument getResXmlDocument() {
return mDocument;
}
public void closeDocument(){
mCurrentElement = null;
mCurrentText = null;
mEvent = -1;
destroyDocument();
}
private void destroyDocument(){
if(!mDocumentCreatedHere){
return;
}
mDocumentCreatedHere = false;
if(this.mDocument == null){
return;
}
this.mDocument.destroy();
this.mDocument = null;
}
@Override
public void close(){
closeDocument();
}
@Override
public int getAttributeCount() {
return mCurrentElement.getAttributeCount();
}
@Override
public String getAttributeName(int index) {
ResXmlAttribute xmlAttribute = mCurrentElement.getAttributeAt(index);
if(xmlAttribute!=null){
return xmlAttribute.getName();
}
return null;
}
@Override
public String getAttributeValue(int index) {
ResXmlAttribute xmlAttribute = geResXmlAttributeAt(index);
if(xmlAttribute!=null){
return xmlAttribute.getValueString();
}
return null;
}
@Override
public String getAttributeValue(String namespace, String name) {
ResXmlAttribute attribute = getAttribute(namespace, name);
if(attribute != null){
return attribute.getValueString();
}
return null;
}
@Override
public String getPositionDescription() {
return null;
}
@Override
public int getAttributeNameResource(int index) {
ResXmlAttribute attribute = geResXmlAttributeAt(index);
if(attribute!=null){
return attribute.getNameResourceID();
}
return 0;
}
@Override
public int getAttributeListValue(String namespace, String attribute, String[] options, int defaultValue) {
ResXmlAttribute xmlAttribute = getAttribute(namespace, attribute);
if(xmlAttribute == null){
return 0;
}
List<String> list = Arrays.asList(options);
int index = list.indexOf(xmlAttribute.getValueString());
if(index==-1){
return defaultValue;
}
return index;
}
@Override
public boolean getAttributeBooleanValue(String namespace, String attribute, boolean defaultValue) {
ResXmlAttribute xmlAttribute = getAttribute(namespace, attribute);
if(xmlAttribute == null || xmlAttribute.getValueType() != ValueType.INT_BOOLEAN){
return defaultValue;
}
return xmlAttribute.getValueAsBoolean();
}
@Override
public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
ResXmlAttribute xmlAttribute = getAttribute(namespace, attribute);
if(xmlAttribute == null){
return 0;
}
ValueType valueType=xmlAttribute.getValueType();
if(valueType==ValueType.ATTRIBUTE
||valueType==ValueType.REFERENCE
||valueType==ValueType.DYNAMIC_ATTRIBUTE
||valueType==ValueType.DYNAMIC_REFERENCE){
return xmlAttribute.getData();
}
return defaultValue;
}
@Override
public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
ResXmlAttribute xmlAttribute = getAttribute(namespace, attribute);
if(xmlAttribute == null){
return 0;
}
ValueType valueType=xmlAttribute.getValueType();
if(valueType==ValueType.INT_DEC
||valueType==ValueType.INT_HEX){
return xmlAttribute.getData();
}
return defaultValue;
}
@Override
public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) {
ResXmlAttribute xmlAttribute = getAttribute(namespace, attribute);
if(xmlAttribute == null){
return 0;
}
ValueType valueType=xmlAttribute.getValueType();
if(valueType==ValueType.INT_DEC){
return xmlAttribute.getData();
}
return defaultValue;
}
@Override
public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) {
ResXmlAttribute xmlAttribute = getAttribute(namespace, attribute);
if(xmlAttribute == null){
return 0;
}
ValueType valueType=xmlAttribute.getValueType();
if(valueType==ValueType.FLOAT){
return Float.intBitsToFloat(xmlAttribute.getData());
}
return defaultValue;
}
@Override
public int getAttributeListValue(int index, String[] options, int defaultValue) {
ResXmlAttribute xmlAttribute = geResXmlAttributeAt(index);
if(xmlAttribute == null){
return 0;
}
List<String> list = Arrays.asList(options);
int i = list.indexOf(xmlAttribute.getValueString());
if(i==-1){
return defaultValue;
}
return index;
}
@Override
public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
ResXmlAttribute xmlAttribute = geResXmlAttributeAt(index);
if(xmlAttribute == null || xmlAttribute.getValueType() != ValueType.INT_BOOLEAN){
return defaultValue;
}
return xmlAttribute.getValueAsBoolean();
}
@Override
public int getAttributeResourceValue(int index, int defaultValue) {
ResXmlAttribute xmlAttribute = geResXmlAttributeAt(index);
if(xmlAttribute == null){
return 0;
}
ValueType valueType=xmlAttribute.getValueType();
if(valueType==ValueType.ATTRIBUTE
||valueType==ValueType.REFERENCE
||valueType==ValueType.DYNAMIC_ATTRIBUTE
||valueType==ValueType.DYNAMIC_REFERENCE){
return xmlAttribute.getData();
}
return defaultValue;
}
@Override
public int getAttributeIntValue(int index, int defaultValue) {
ResXmlAttribute xmlAttribute = geResXmlAttributeAt(index);
if(xmlAttribute == null){
return 0;
}
ValueType valueType=xmlAttribute.getValueType();
if(valueType==ValueType.INT_DEC
||valueType==ValueType.INT_HEX){
return xmlAttribute.getData();
}
return defaultValue;
}
@Override
public int getAttributeUnsignedIntValue(int index, int defaultValue) {
ResXmlAttribute xmlAttribute = geResXmlAttributeAt(index);
if(xmlAttribute == null){
return 0;
}
ValueType valueType=xmlAttribute.getValueType();
if(valueType==ValueType.INT_DEC){
return xmlAttribute.getData();
}
return defaultValue;
}
@Override
public float getAttributeFloatValue(int index, float defaultValue) {
ResXmlAttribute xmlAttribute = geResXmlAttributeAt(index);
if(xmlAttribute == null){
return 0;
}
ValueType valueType=xmlAttribute.getValueType();
if(valueType==ValueType.FLOAT){
return Float.intBitsToFloat(xmlAttribute.getData());
}
return defaultValue;
}
@Override
public String getIdAttribute() {
ResXmlStartElement startElement = getResXmlStartElement();
if(startElement!=null){
ResXmlAttribute attribute = startElement.getIdAttribute();
if(attribute!=null){
return attribute.getName();
}
}
return null;
}
@Override
public String getClassAttribute() {
ResXmlStartElement startElement = getResXmlStartElement();
if(startElement!=null){
ResXmlAttribute attribute = startElement.getClassAttribute();
if(attribute!=null){
return attribute.getName();
}
}
return null;
}
@Override
public int getIdAttributeResourceValue(int defaultValue) {
ResXmlStartElement startElement = getResXmlStartElement();
if(startElement!=null){
ResXmlAttribute attribute = startElement.getIdAttribute();
if(attribute!=null){
return attribute.getNameResourceID();
}
}
return 0;
}
@Override
public int getStyleAttribute() {
ResXmlStartElement startElement = getResXmlStartElement();
if(startElement!=null){
ResXmlAttribute attribute = startElement.getStyleAttribute();
if(attribute!=null){
return attribute.getNameResourceID();
}
}
return 0;
}
@Override
public void setFeature(String name, boolean state) throws XmlPullParserException {
}
@Override
public boolean getFeature(String name) {
return false;
}
@Override
public void setProperty(String name, Object value) throws XmlPullParserException {
}
@Override
public Object getProperty(String name) {
return null;
}
@Override
public void setInput(Reader in) throws XmlPullParserException {
InputStream inputStream = getFromLock(in);
if(inputStream == null){
throw new XmlPullParserException("Can't parse binary xml from reader");
}
setInput(inputStream, null);
}
@Override
public void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException {
ResXmlDocument xmlDocument = new ResXmlDocument();
try {
xmlDocument.readBytes(inputStream);
} catch (IOException exception) {
XmlPullParserException pullParserException = new XmlPullParserException(exception.getMessage());
pullParserException.initCause(exception);
throw pullParserException;
}
setResXmlDocument(xmlDocument);
this.mDocumentCreatedHere = true;
}
@Override
public String getInputEncoding() {
return null;
}
@Override
public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException {
}
@Override
public int getNamespaceCount(int depth) throws XmlPullParserException {
ResXmlElement element = getCurrentElement();
while(element!=null && element.getDepth()>depth){
element=element.getParentResXmlElement();
}
if(element!=null){
return element.getStartNamespaceList().size();
}
return 0;
}
@Override
public String getNamespacePrefix(int pos) throws XmlPullParserException {
ResXmlAttribute attribute = mCurrentElement.getAttributeAt(pos);
if(attribute!=null){
return attribute.getNamePrefix();
}
return null;
}
@Override
public String getNamespaceUri(int pos) throws XmlPullParserException {
ResXmlAttribute attribute = mCurrentElement.getAttributeAt(pos);
if(attribute!=null){
return attribute.getUri();
}
return null;
}
@Override
public String getNamespace(String prefix) {
ResXmlStartNamespace startNamespace = mCurrentElement.getStartNamespaceByPrefix(prefix);
if(startNamespace!=null){
return startNamespace.getUri();
}
return null;
}
@Override
public int getDepth() {
int event = mEvent;
if(event == START_TAG || event == END_TAG){
return mCurrentElement.getDepth();
}
if(event == TEXT){
return mCurrentText.getDepth();
}
return 0;
}
@Override
public int getLineNumber() {
int event = mEvent;
if(event == START_TAG){
ResXmlStartElement startElement = mCurrentElement.getStartElement();
if(startElement!=null){
return startElement.getLineNumber();
}
return 0;
}
if(event == END_TAG){
ResXmlEndElement endElement = mCurrentElement.getEndElement();
if(endElement!=null){
return endElement.getLineNumber();
}
return 0;
}
if(event == TEXT){
return mCurrentText.getLineNumber();
}
return 0;
}
@Override
public int getColumnNumber() {
return 0;
}
@Override
public boolean isWhitespace() throws XmlPullParserException {
return false;
}
@Override
public String getText() {
int event = mEvent;
if(event == TEXT){
return mCurrentText.getText();
}
if(event == START_TAG || event == END_TAG){
return mCurrentElement.getTag();
}
return null;
}
@Override
public char[] getTextCharacters(int[] holderForStartAndLength) {
String text = getText();
if (text == null) {
holderForStartAndLength[0] = -1;
holderForStartAndLength[1] = -1;
return null;
}
char[] result = text.toCharArray();
holderForStartAndLength[0] = 0;
holderForStartAndLength[1] = result.length;
return result;
}
@Override
public String getNamespace() {
ResXmlElement element = getCurrentElement();
if(element!=null){
return element.getTagUri();
}
return null;
}
@Override
public String getName() {
ResXmlElement element = getCurrentElement();
if(element!=null){
return element.getTag();
}
return null;
}
@Override
public String getPrefix() {
ResXmlElement element = getCurrentElement();
if(element!=null){
return element.getTagPrefix();
}
return null;
}
@Override
public boolean isEmptyElementTag() throws XmlPullParserException {
ResXmlElement element = getCurrentElement();
if(element!=null){
return element.countResXmlNodes() == 0 && element.getAttributeCount()==0;
}
return false;
}
@Override
public String getAttributeNamespace(int index) {
ResXmlAttribute attribute = geResXmlAttributeAt(index);
if(attribute != null){
return attribute.getUri();
}
return null;
}
@Override
public String getAttributePrefix(int index) {
ResXmlAttribute attribute = geResXmlAttributeAt(index);
if(attribute != null){
return attribute.getNamePrefix();
}
return null;
}
@Override
public String getAttributeType(int index) {
return "CDATA";
}
@Override
public boolean isAttributeDefault(int index) {
return false;
}
private ResXmlAttribute geResXmlAttributeAt(int index){
ResXmlElement element = getCurrentElement();
if(element == null){
return null;
}
return element.getAttributeAt(index);
}
private ResXmlAttribute getAttribute(String namespace, String name) {
ResXmlElement element = getCurrentElement();
if(element == null){
return null;
}
for(ResXmlAttribute attribute:element.listAttributes()){
if(Objects.equals(namespace, attribute.getUri())
&& Objects.equals(name, attribute.getName())){
return attribute;
}
}
return null;
}
private ResXmlStartElement getResXmlStartElement(){
ResXmlElement element = getCurrentElement();
if(element!=null){
return element.getStartElement();
}
return null;
}
private ResXmlElement getCurrentElement() {
int event = mEvent;
if(event!=START_TAG && event!=END_TAG){
return null;
}
return mCurrentElement;
}
@Override
public int getEventType() throws XmlPullParserException {
return mEvent;
}
@Override
public int next() throws XmlPullParserException, IOException {
checkNotEnded();
int event = calculateNextEvent(mEvent);
if(event == START_DOCUMENT){
onStartDocument();
}else if(event == END_DOCUMENT){
onEndDocument();
}else if(event == START_TAG){
onStartTag();
}else if(event == END_TAG){
onEndTag();
}else if(event == TEXT){
onText();
}
this.mEvent = event;
return event;
}
private void onEndTag() throws XmlPullParserException {
int previous = mEvent;
if(previous == END_TAG){
mCurrentElement = mCurrentElement.getParentResXmlElement();
}
mCurrentText = null;
}
private void onText() throws XmlPullParserException {
int previous = mEvent;
if(previous == END_TAG){
int position = mCurrentElement.getIndex();
ResXmlElement parent = mCurrentElement.getParentResXmlElement();
position++;
mCurrentText = (ResXmlTextNode) parent.getResXmlNode(position);
mCurrentElement = parent;
}else if(previous == START_TAG){
ResXmlElement parent = mCurrentElement;
mCurrentText = (ResXmlTextNode) parent.getResXmlNode(0);
}else if(previous == TEXT){
int position = mCurrentText.getIndex();
ResXmlElement parent = mCurrentElement;
position++;
mCurrentText = (ResXmlTextNode) parent.getResXmlNode(position);
mCurrentText = (ResXmlTextNode) parent.getResXmlNode(0);
}else {
throw new XmlPullParserException("Unknown state at onText() prev="+previous);
}
}
private void onStartTag() throws XmlPullParserException {
int previous = mEvent;
if(previous == START_DOCUMENT){
mCurrentElement = mDocument.getResXmlElement();
mCurrentText = null;
}else if(previous == END_TAG){
int position = mCurrentElement.getIndex();
ResXmlElement parent = mCurrentElement.getParentResXmlElement();
position++;
mCurrentElement = (ResXmlElement) parent.getResXmlNode(position);
}else if(previous == TEXT){
int position = mCurrentText.getIndex();
ResXmlElement parent = mCurrentText.getResXmlText().getParentResXmlElement();
position++;
mCurrentElement = (ResXmlElement) parent.getResXmlNode(position);
}else if(previous == START_TAG){
mCurrentElement = (ResXmlElement) mCurrentElement.getResXmlNode(0);
}else {
throw new XmlPullParserException("Unknown state at onStartTag() prev="+previous);
}
mCurrentText = null;
}
private void onStartDocument(){
}
private void onEndDocument() throws XmlPullParserException {
mCurrentElement = null;
mCurrentText = null;
close();
}
private void checkNotEnded() throws XmlPullParserException {
if(mEvent == END_DOCUMENT){
throw new XmlPullParserException("Document reached to end");
}
}
private int calculateNextEvent(int previous) throws XmlPullParserException {
if(previous < 0){
if(mDocument == null){
return previous;
}
return START_DOCUMENT;
}
if(previous == START_DOCUMENT){
ResXmlElement element = mDocument.getResXmlElement();
if(element==null){
return END_DOCUMENT;
}
return START_TAG;
}
if(previous == END_DOCUMENT){
return END_DOCUMENT;
}
if(previous == START_TAG){
ResXmlElement element = mCurrentElement;
ResXmlNode firstChild = element.getResXmlNode(0);
if(firstChild == null){
return END_TAG;
}
if(firstChild instanceof ResXmlTextNode){
return TEXT;
}
return START_TAG;
}
if(previous == END_TAG || previous==TEXT){
ResXmlElement element = mCurrentElement;
ResXmlElement parent = element.getParentResXmlElement();
if(parent == null){
return END_DOCUMENT;
}
int position = element.getIndex() + 1;
ResXmlNode nextNode = parent.getResXmlNode(position);
if(nextNode==null){
return END_TAG;
}
if(nextNode instanceof ResXmlTextNode){
return TEXT;
}
return START_TAG;
}
throw new XmlPullParserException("Unknown state at calculateNextEvent() prev="+previous);
}
@Override
public int nextToken() throws XmlPullParserException, IOException {
return next();
}
@Override
public void require(int type, String namespace, String name) throws XmlPullParserException, IOException {
}
@Override
public String nextText() throws XmlPullParserException, IOException {
return null;
}
@Override
public int nextTag() throws XmlPullParserException, IOException {
return 0;
}
private static InputStream getFromLock(Reader reader){
try{
Field field = Reader.class.getDeclaredField("lock");
field.setAccessible(true);
Object obj = field.get(reader);
if(obj instanceof InputStream){
return (InputStream) obj;
}
}catch (Throwable ignored){
}
return null;
}
/**
* This non-final re-declaration is to force compiler from using literal int value on this class
* */
}

View File

@ -52,6 +52,15 @@
addChild(mStyleAttributePosition); addChild(mStyleAttributePosition);
addChild(mAttributeArray); addChild(mAttributeArray);
} }
public ResXmlAttribute getIdAttribute(){
return getResXmlAttributeArray().get(mIdAttributePosition.unsignedInt()-1);
}
public ResXmlAttribute getClassAttribute(){
return getResXmlAttributeArray().get(mClassAttributePosition.unsignedInt()-1);
}
public ResXmlAttribute getStyleAttribute(){
return getResXmlAttributeArray().get(mStyleAttributePosition.unsignedInt()-1);
}
void setAttributesUnitSize(int size){ void setAttributesUnitSize(int size){
mAttributeArray.setAttributesUnitSize(size); mAttributeArray.setAttributesUnitSize(size);
} }

View File

@ -35,6 +35,22 @@ public class ResXmlTextNode extends ResXmlNode {
public int getLineNumber(){ public int getLineNumber(){
return getResXmlText().getLineNumber(); return getResXmlText().getLineNumber();
} }
@Override
public String getComment() {
return getResXmlText().getComment();
}
@Override
public int getDepth(){
ResXmlElement parent = getParentResXmlElement();
if(parent!=null){
return parent.getDepth() + 1;
}
return 0;
}
public ResXmlElement getParentResXmlElement(){
return getResXmlText().getParentResXmlElement();
}
public void setLineNumber(int lineNumber){ public void setLineNumber(int lineNumber){
getResXmlText().setLineNumber(lineNumber); getResXmlText().setLineNumber(lineNumber);
} }

View File

@ -57,6 +57,9 @@ public class BlockList<T extends Block> extends Block {
mItems.add(item); mItems.add(item);
} }
public T get(int i){ public T get(int i){
if(i>=mItems.size() || i<0){
return null;
}
return mItems.get(i); return mItems.get(i);
} }
public int size(){ public int size(){

View File

@ -118,6 +118,9 @@ import java.util.Objects;
public StringItem getDataAsPoolString(){ public StringItem getDataAsPoolString(){
if(getValueType()!=ValueType.STRING){
return null;
}
StringPool<?> stringPool = getStringPool(); StringPool<?> stringPool = getStringPool();
if(stringPool == null){ if(stringPool == null){
return null; return null;

View File

@ -15,7 +15,10 @@
*/ */
package com.reandroid.xml.parser; package com.reandroid.xml.parser;
import com.android.org.kxml2.io.KXmlParser;
import com.reandroid.xml.*; import com.reandroid.xml.*;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.*; import java.io.*;
import java.util.ArrayList; import java.util.ArrayList;
@ -343,7 +346,7 @@ public class XMLDocumentParser {
} }
private static XmlPullParser createParser(InputStream in) throws XMLParseException { private static XmlPullParser createParser(InputStream in) throws XMLParseException {
try { try {
XmlPullParser parser = new MXParserNonValidating(); XmlPullParser parser = new KXmlParser();
parser.setInput(in, null); parser.setInput(in, null);
return parser; return parser;
} catch (XmlPullParserException e) { } catch (XmlPullParserException e) {

View File

@ -12,6 +12,7 @@ import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
@Deprecated
public interface XmlPullParser { public interface XmlPullParser {
String NO_NAMESPACE = ""; String NO_NAMESPACE = "";

View File

@ -8,6 +8,7 @@
/*This package is renamed from org.xmlpull.* to avoid conflicts*/ /*This package is renamed from org.xmlpull.* to avoid conflicts*/
package com.reandroid.xml.parser; package com.reandroid.xml.parser;
@Deprecated
public class XmlPullParserException extends Exception { public class XmlPullParserException extends Exception {
protected Throwable detail; protected Throwable detail;
protected int row = -1; protected int row = -1;

View File

@ -0,0 +1,78 @@
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
package org.xmlpull.v1;
import java.io.InputStream;
import java.io.IOException;
import java.io.Reader;
public interface XmlPullParser{
String NO_NAMESPACE = "";
int START_DOCUMENT = 0;
int END_DOCUMENT = 1;
int START_TAG = 2;
int END_TAG = 3;
int TEXT = 4;
int CDSECT = 5;
int ENTITY_REF = 6;
int IGNORABLE_WHITESPACE = 7;
int PROCESSING_INSTRUCTION = 8;
int COMMENT = 9;
int DOCDECL = 10;
String [] TYPES = {
"START_DOCUMENT",
"END_DOCUMENT",
"START_TAG",
"END_TAG",
"TEXT",
"CDSECT",
"ENTITY_REF",
"IGNORABLE_WHITESPACE",
"PROCESSING_INSTRUCTION",
"COMMENT",
"DOCDECL"
};
String FEATURE_PROCESS_NAMESPACES = "http://xmlpull.org/v1/doc/features.html#process-namespaces";
String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";
String FEATURE_PROCESS_DOCDECL = "http://xmlpull.org/v1/doc/features.html#process-docdecl";
String FEATURE_VALIDATION = "http://xmlpull.org/v1/doc/features.html#validation";
void setFeature(String name, boolean state) throws XmlPullParserException;
boolean getFeature(String name);
void setProperty(String name, Object value) throws XmlPullParserException;
Object getProperty(String name);
void setInput(Reader in) throws XmlPullParserException;
void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException;
String getInputEncoding();
void defineEntityReplacementText( String entityName, String replacementText ) throws XmlPullParserException;
int getNamespaceCount(int depth) throws XmlPullParserException;
String getNamespacePrefix(int pos) throws XmlPullParserException;
String getNamespaceUri(int pos) throws XmlPullParserException;
String getNamespace (String prefix);
int getDepth();
String getPositionDescription ();
int getLineNumber();
int getColumnNumber();
boolean isWhitespace() throws XmlPullParserException;
String getText ();
char[] getTextCharacters(int [] holderForStartAndLength);
String getNamespace ();
String getName();
String getPrefix();
boolean isEmptyElementTag() throws XmlPullParserException;
int getAttributeCount();
String getAttributeNamespace (int index);
String getAttributeName (int index);
String getAttributePrefix(int index);
String getAttributeType(int index);
boolean isAttributeDefault(int index);
String getAttributeValue(int index);
String getAttributeValue(String namespace, String name);
int getEventType() throws XmlPullParserException;
int next() throws XmlPullParserException, IOException;
int nextToken() throws XmlPullParserException, IOException;
void require(int type, String namespace, String name) throws XmlPullParserException, IOException;
String nextText() throws XmlPullParserException, IOException;
int nextTag() throws XmlPullParserException, IOException;
}

View File

@ -0,0 +1,76 @@
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
package org.xmlpull.v1;
/**
* This exception is thrown to signal XML Pull Parser related faults.
*
* @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
*/
public class XmlPullParserException extends Exception{
protected Throwable detail;
protected int row = -1;
protected int column = -1;
/* public XmlPullParserException() {
}*/
public XmlPullParserException(String s) {
super(s);
}
/*
public XmlPullParserException(String s, Throwable thrwble) {
super(s);
this.detail = thrwble;
}
public XmlPullParserException(String s, int row, int column) {
super(s);
this.row = row;
this.column = column;
}
*/
public XmlPullParserException(String msg, XmlPullParser parser, Throwable chain) {
super ((msg == null ? "" : msg+" ")
+ (parser == null ? "" : "(position:"+parser.getPositionDescription()+") ")
+ (chain == null ? "" : "caused by: "+chain));
if (parser != null) {
this.row = parser.getLineNumber();
this.column = parser.getColumnNumber();
}
this.detail = chain;
}
public Throwable getDetail() { return detail; }
// public void setDetail(Throwable cause) { this.detail = cause; }
public int getLineNumber() { return row; }
public int getColumnNumber() { return column; }
/*
public String getMessage() {
if(detail == null)
return super.getMessage();
else
return super.getMessage() + "; nested exception is: \n\t"
+ detail.getMessage();
}
*/
//NOTE: code that prints this and detail is difficult in J2ME
public void printStackTrace() {
if (detail == null) {
super.printStackTrace();
} else {
synchronized(System.err) {
System.err.println(super.getMessage() + "; nested exception is:");
detail.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,119 @@
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
package org.xmlpull.v1;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class XmlPullParserFactory {
public static final String PROPERTY_NAME = "org.xmlpull.v1.XmlPullParserFactory";
protected ArrayList parserClasses;
protected ArrayList serializerClasses;
protected String classNamesLocation = null;
protected HashMap<String, Boolean> features = new HashMap<String, Boolean>();
protected XmlPullParserFactory() {
parserClasses = new ArrayList<String>();
serializerClasses = new ArrayList<String>();
try {
parserClasses.add(Class.forName("com.android.org.kxml2.io.KXmlParser"));
serializerClasses.add(Class.forName("com.android.org.kxml2.io.KXmlSerializer"));
} catch (ClassNotFoundException e) {
throw new AssertionError();
}
}
public void setFeature(String name, boolean state) throws XmlPullParserException {
features.put(name, state);
}
public boolean getFeature(String name) {
Boolean value = features.get(name);
return value != null ? value.booleanValue() : false;
}
public void setNamespaceAware(boolean awareness) {
features.put (XmlPullParser.FEATURE_PROCESS_NAMESPACES, awareness);
}
public boolean isNamespaceAware() {
return getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES);
}
public void setValidating(boolean validating) {
features.put(XmlPullParser.FEATURE_VALIDATION, validating);
}
public boolean isValidating() {
return getFeature(XmlPullParser.FEATURE_VALIDATION);
}
public XmlPullParser newPullParser() throws XmlPullParserException {
final XmlPullParser pp = getParserInstance();
for (Map.Entry<String, Boolean> entry : features.entrySet()) {
if (entry.getValue()) {
pp.setFeature(entry.getKey(), entry.getValue());
}
}
return pp;
}
private XmlPullParser getParserInstance() throws XmlPullParserException {
ArrayList<Exception> exceptions = null;
if (parserClasses != null && !parserClasses.isEmpty()) {
exceptions = new ArrayList<Exception>();
for (Object o : parserClasses) {
try {
if (o != null) {
Class<?> parserClass = (Class<?>) o;
return (XmlPullParser) parserClass.newInstance();
}
} catch (InstantiationException e) {
exceptions.add(e);
} catch (IllegalAccessException e) {
exceptions.add(e);
} catch (ClassCastException e) {
exceptions.add(e);
}
}
}
throw newInstantiationException("Invalid parser class list", exceptions);
}
private XmlSerializer getSerializerInstance() throws XmlPullParserException {
ArrayList<Exception> exceptions = null;
if (serializerClasses != null && !serializerClasses.isEmpty()) {
exceptions = new ArrayList<Exception>();
for (Object o : serializerClasses) {
try {
if (o != null) {
Class<?> serializerClass = (Class<?>) o;
return (XmlSerializer) serializerClass.newInstance();
}
} catch (InstantiationException e) {
exceptions.add(e);
} catch (IllegalAccessException e) {
exceptions.add(e);
} catch (ClassCastException e) {
exceptions.add(e);
}
}
}
throw newInstantiationException("Invalid serializer class list", exceptions);
}
private static XmlPullParserException newInstantiationException(String message,
ArrayList<Exception> exceptions) {
if (exceptions == null || exceptions.isEmpty()) {
return new XmlPullParserException(message);
} else {
XmlPullParserException exception = new XmlPullParserException(message);
for (Exception ex : exceptions) {
exception.addSuppressed(ex);
}
return exception;
}
}
public XmlSerializer newSerializer() throws XmlPullParserException {
return getSerializerInstance();
}
public static XmlPullParserFactory newInstance () throws XmlPullParserException {
return new XmlPullParserFactory();
}
public static XmlPullParserFactory newInstance (String unused, Class unused2)
throws XmlPullParserException {
return newInstance();
}
}

View File

@ -0,0 +1,52 @@
package org.xmlpull.v1;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
public interface XmlSerializer {
void setFeature(String name, boolean state)
throws IllegalArgumentException, IllegalStateException;
boolean getFeature(String name);
void setProperty(String name, Object value)
throws IllegalArgumentException, IllegalStateException;
Object getProperty(String name);
void setOutput(OutputStream os, String encoding)
throws IOException, IllegalArgumentException, IllegalStateException;
void setOutput(Writer writer)
throws IOException, IllegalArgumentException, IllegalStateException;
void startDocument(String encoding, Boolean standalone)
throws IOException, IllegalArgumentException, IllegalStateException;
void endDocument()
throws IOException, IllegalArgumentException, IllegalStateException;
void setPrefix(String prefix, String namespace)
throws IOException, IllegalArgumentException, IllegalStateException;
String getPrefix(String namespace, boolean generatePrefix)
throws IllegalArgumentException;
int getDepth();
String getNamespace();
String getName();
XmlSerializer startTag(String namespace, String name)
throws IOException, IllegalArgumentException, IllegalStateException;
XmlSerializer attribute(String namespace, String name, String value)
throws IOException, IllegalArgumentException, IllegalStateException;
XmlSerializer endTag(String namespace, String name)
throws IOException, IllegalArgumentException, IllegalStateException;
XmlSerializer text(String text)
throws IOException, IllegalArgumentException, IllegalStateException;
XmlSerializer text(char [] buf, int start, int len)
throws IOException, IllegalArgumentException, IllegalStateException;
void cdsect(String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void entityRef(String text) throws IOException,
IllegalArgumentException, IllegalStateException;
void processingInstruction(String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void comment(String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void docdecl(String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void ignorableWhitespace(String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void flush() throws IOException;
}