From b8d410803d7c74f2df5e02b03235b3af8fbba778 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Wed, 3 May 2023 17:09:45 +0200 Subject: [PATCH] implement namespace features as per xmlpull #18 --- .../arsc/chunk/xml/ResXmlPullParser.java | 33 ++++++---- .../reandroid/xml/XmlParserToSerializer.java | 64 ++++++++++++++++--- 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlPullParser.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlPullParser.java index 439bf7f6a..e1c7baf14 100644 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlPullParser.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlPullParser.java @@ -36,11 +36,12 @@ public class ResXmlPullParser implements XmlResourceParser { private DocumentLoadedListener documentLoadedListener; private boolean processNamespaces; private boolean reportNamespaceAttrs; + private boolean mIsTagStared; public ResXmlPullParser(Decoder decoder){ this.mDecoder = decoder; - this.processNamespaces = true; - this.reportNamespaceAttrs = true; + this.processNamespaces = false; + this.reportNamespaceAttrs = false; } public ResXmlPullParser(){ this(null); @@ -93,6 +94,7 @@ private void initializeDecoder(ResXmlDocument xmlDocument){ public void closeDocument(){ mEventList.clear(); + mIsTagStared = false; destroyDocument(); } private void destroyDocument(){ @@ -118,14 +120,14 @@ public int getAttributeCount() { return 0; } int count = element.getAttributeCount(); - if(reportNamespaceAttrs){ + if(isCountNamespacesAsAttribute()){ count += element.getNamespaceCount(); } return count; } @Override public String getAttributeName(int index) { - if(reportNamespaceAttrs){ + if(isCountNamespacesAsAttribute()){ int nsCount = getNamespaceCountInternal(); if(index < nsCount){ return getNamespaceAttributeName(index); @@ -135,7 +137,7 @@ public String getAttributeName(int index) { } @Override public String getAttributeValue(int index) { - if(reportNamespaceAttrs){ + if(isCountNamespacesAsAttribute()){ int nsCount = getNamespaceCountInternal(); if(index < nsCount){ return getNamespaceAttributeValue(index); @@ -345,13 +347,20 @@ public int getStyleAttribute() { @Override public void setFeature(String name, boolean state) throws XmlPullParserException { + boolean changed; if(FEATURE_PROCESS_NAMESPACES.equals(name)) { + changed = processNamespaces != state; processNamespaces = state; }else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) { + changed = reportNamespaceAttrs != state; reportNamespaceAttrs = state; }else { throw new XmlPullParserException("Unsupported feature: " + name); } + if(changed && mIsTagStared){ + throw new XmlPullParserException("Feature changed during parsing: " + + name + ", state=" + state); + } } @Override @@ -392,7 +401,7 @@ public void defineEntityReplacementText(String entityName, String replacementTex } @Override public int getNamespaceCount(int depth) throws XmlPullParserException { - if(reportNamespaceAttrs){ + if(isCountNamespacesAsAttribute()){ return 0; } ResXmlElement element = getCurrentElement(); @@ -593,7 +602,7 @@ public ResXmlElement getCurrentElement() { return null; } private int getRealAttributeIndex(int index){ - if(reportNamespaceAttrs){ + if(isCountNamespacesAsAttribute()){ index = index - getNamespaceCountInternal(); } return index; @@ -605,6 +614,9 @@ private int getNamespaceCountInternal(){ } return 0; } + private boolean isCountNamespacesAsAttribute(){ + return processNamespaces & reportNamespaceAttrs; + } private String getNamespaceAttributeName(int index){ ResXmlStartNamespace namespace = getCurrentElement() .getNamespace(index); @@ -628,9 +640,9 @@ public int next() throws XmlPullParserException, IOException { mEventList.next(); int type = mEventList.getType(); if(type == START_TAG){ - onStartTag(); + mIsTagStared = true; } - return mEventList.getType(); + return type; } @Override public int nextToken() throws XmlPullParserException, IOException { @@ -711,9 +723,6 @@ private void initDefaultFeatures(){ processNamespaces = true; reportNamespaceAttrs = true; } - private void onStartTag(){ - - } public static interface DocumentLoadedListener{ public ResXmlDocument onDocumentLoaded(ResXmlDocument resXmlDocument); diff --git a/src/main/java/com/reandroid/xml/XmlParserToSerializer.java b/src/main/java/com/reandroid/xml/XmlParserToSerializer.java index b4c386213..0e324adbd 100644 --- a/src/main/java/com/reandroid/xml/XmlParserToSerializer.java +++ b/src/main/java/com/reandroid/xml/XmlParserToSerializer.java @@ -20,17 +20,22 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import java.io.Closeable; import java.io.IOException; public class XmlParserToSerializer { private final XmlSerializer serializer; - private final XmlResourceParser parser; + private final XmlPullParser parser; private boolean enableIndent; + boolean processNamespace; + boolean reportNamespaceAttrs; - public XmlParserToSerializer(XmlResourceParser parser, XmlSerializer serializer){ + public XmlParserToSerializer(XmlPullParser parser, XmlSerializer serializer){ this.parser = parser; this.serializer = serializer; this.enableIndent = true; + setFeatureSafe(parser, XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + setFeatureSafe(parser, XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES, true); } public void setEnableIndent(boolean enableIndent) { @@ -38,15 +43,29 @@ public void setEnableIndent(boolean enableIndent) { } public void write() throws IOException, XmlPullParserException { - XmlResourceParser parser = this.parser; + XmlPullParser parser = this.parser; + + this.processNamespace = getFeatureSafe(parser, + XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); + + this.reportNamespaceAttrs = getFeatureSafe(parser, + XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES, false); + int event = parser.next(); while (nextEvent(event)){ event = parser.next(); } close(); } - private void close(){ - parser.close(); + private void close() throws IOException { + XmlPullParser parser = this.parser; + if(parser instanceof Closeable){ + ((Closeable)parser).close(); + } + XmlSerializer serializer = this.serializer; + if(serializer instanceof Closeable){ + ((Closeable)serializer).close(); + } } private boolean nextEvent(int event) throws IOException, XmlPullParserException { boolean hasNext = true; @@ -78,12 +97,17 @@ private void onStartDocument() throws IOException{ serializer.startDocument("utf-8", null); } private void onStartTag() throws IOException, XmlPullParserException { - XmlResourceParser parser = this.parser; + XmlPullParser parser = this.parser; XmlSerializer serializer = this.serializer; - boolean processNamespace = parser.getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES); - boolean reportNamespaceAttrs = parser.getFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES); - serializer.setFeature(FEATURE_INDENT_OUTPUT, enableIndent); - if(!reportNamespaceAttrs){ + + boolean processNamespace = this.processNamespace; + boolean countNamespaceAsAttribute = processNamespace && reportNamespaceAttrs; + + if(enableIndent){ + setFeatureSafe(serializer, FEATURE_INDENT_OUTPUT, true); + } + + if(!countNamespaceAsAttribute){ int nsCount = parser.getNamespaceCount(parser.getDepth()); for(int i=0; i