implement namespace features as per xmlpull #18

This commit is contained in:
REAndroid 2023-05-03 17:09:45 +02:00
parent db3a18b039
commit b8d410803d
2 changed files with 75 additions and 22 deletions

View File

@ -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 @@ public class ResXmlPullParser implements XmlResourceParser {
public void closeDocument(){
mEventList.clear();
mIsTagStared = false;
destroyDocument();
}
private void destroyDocument(){
@ -118,14 +120,14 @@ public class ResXmlPullParser implements XmlResourceParser {
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 class ResXmlPullParser implements XmlResourceParser {
}
@Override
public String getAttributeValue(int index) {
if(reportNamespaceAttrs){
if(isCountNamespacesAsAttribute()){
int nsCount = getNamespaceCountInternal();
if(index < nsCount){
return getNamespaceAttributeValue(index);
@ -345,13 +347,20 @@ public class ResXmlPullParser implements XmlResourceParser {
@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 class ResXmlPullParser implements XmlResourceParser {
}
@Override
public int getNamespaceCount(int depth) throws XmlPullParserException {
if(reportNamespaceAttrs){
if(isCountNamespacesAsAttribute()){
return 0;
}
ResXmlElement element = getCurrentElement();
@ -593,7 +602,7 @@ public class ResXmlPullParser implements XmlResourceParser {
return null;
}
private int getRealAttributeIndex(int index){
if(reportNamespaceAttrs){
if(isCountNamespacesAsAttribute()){
index = index - getNamespaceCountInternal();
}
return index;
@ -605,6 +614,9 @@ public class ResXmlPullParser implements XmlResourceParser {
}
return 0;
}
private boolean isCountNamespacesAsAttribute(){
return processNamespaces & reportNamespaceAttrs;
}
private String getNamespaceAttributeName(int index){
ResXmlStartNamespace namespace = getCurrentElement()
.getNamespace(index);
@ -628,9 +640,9 @@ public class ResXmlPullParser implements XmlResourceParser {
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 @@ public class ResXmlPullParser implements XmlResourceParser {
processNamespaces = true;
reportNamespaceAttrs = true;
}
private void onStartTag(){
}
public static interface DocumentLoadedListener{
public ResXmlDocument onDocumentLoaded(ResXmlDocument resXmlDocument);

View File

@ -20,17 +20,22 @@ import org.xmlpull.v1.XmlPullParser;
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 class XmlParserToSerializer {
}
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 @@ public class XmlParserToSerializer {
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<nsCount; i++){
String prefix = parser.getNamespacePrefix(i);
@ -115,5 +139,25 @@ public class XmlParserToSerializer {
serializer.endDocument();
}
private static boolean getFeatureSafe(XmlPullParser parser, String name, boolean def){
try{
return parser.getFeature(name);
}catch (Throwable ignored){
return def;
}
}
private static void setFeatureSafe(XmlPullParser parser, String name, boolean state){
try{
parser.setFeature(name, state);
}catch (Throwable ignored){
}
}
private static void setFeatureSafe(XmlSerializer serializer, String name, boolean state){
try{
serializer.setFeature(name, state);
}catch (Throwable ignored){
}
}
private static final String FEATURE_INDENT_OUTPUT = "http://xmlpull.org/v1/doc/features.html#indent-output";
}