diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlAttribute.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlAttribute.java
index faf8667a2..c2a1624be 100755
--- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlAttribute.java
+++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlAttribute.java
@@ -722,7 +722,11 @@ public ResourceEntry encodeAttributeName(String uri, String prefix, String name)
setName(name, 0);
return null;
}
- ResourceEntry resourceEntry = super.encodeAttrName(prefix, name);
+ String lookupPrefix = prefix;
+ if (Namespace.URI_ANDROID.equals(uri)) {
+ lookupPrefix = Namespace.PREFIX_ANDROID;
+ }
+ ResourceEntry resourceEntry = super.encodeAttrName(lookupPrefix, name);
if (resourceEntry != null) {
return resourceEntry;
}
diff --git a/src/test/java/com/reandroid/arsc/chunk/xml/Pr111NamespaceRegressionTest.java b/src/test/java/com/reandroid/arsc/chunk/xml/Pr111NamespaceRegressionTest.java
new file mode 100644
index 000000000..7ebf63ba2
--- /dev/null
+++ b/src/test/java/com/reandroid/arsc/chunk/xml/Pr111NamespaceRegressionTest.java
@@ -0,0 +1,79 @@
+package com.reandroid.arsc.chunk.xml;
+
+import com.reandroid.apk.AndroidFrameworks;
+import com.reandroid.apk.ApkModule;
+import com.reandroid.arsc.chunk.TableBlock;
+import com.reandroid.xml.XMLFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class Pr111NamespaceRegressionTest {
+
+ private ResXmlDocument parse(String xml) throws Exception {
+ TableBlock table = new TableBlock();
+ table.addFramework(
+ AndroidFrameworks.getLatest().getTableBlock());
+ table.refresh();
+
+ ApkModule apk = new ApkModule();
+ apk.setTableBlock(table);
+
+ ResXmlDocument doc = new ResXmlDocument();
+ doc.setApkFile(apk);
+ doc.parse(XMLFactory.newPullParser(xml));
+ return doc;
+ }
+
+ @Test
+ public void standardAndroidPrefix() throws Exception {
+ ResXmlDocument doc = parse(
+ "");
+
+ ResXmlAttribute attr = doc.getDocumentElement()
+ .searchAttributeByName("versionCode");
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals("android", attr.getPrefix());
+ Assert.assertTrue(attr.getNameId() != 0);
+ Assert.assertEquals(123, attr.getData());
+ }
+
+ @Test
+ public void alternateAndroidPrefix() throws Exception {
+ ResXmlDocument doc = parse(
+ "");
+
+ ResXmlAttribute attr = doc.getDocumentElement()
+ .searchAttributeByName("versionCode");
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(
+ "http://schemas.android.com/apk/res/android",
+ attr.getUri());
+ // Prefix may be normalized internally.
+ // Verify namespace URI, resource ID and value instead.
+ Assert.assertTrue(attr.getNameId() != 0);
+ Assert.assertEquals(456, attr.getData());
+ }
+
+ @Test
+ public void externalNamespaceMustNotBecomeAndroid()
+ throws Exception {
+ ResXmlDocument doc = parse(
+ "");
+
+ ResXmlAttribute attr = doc.getDocumentElement()
+ .searchAttributeByName("versionCode");
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(
+ "https://example.com/custom",
+ attr.getUri());
+ Assert.assertEquals(0, attr.getNameId());
+ }
+}
diff --git a/src/test/java/com/reandroid/arsc/chunk/xml/ResXmlDocumentTest.java b/src/test/java/com/reandroid/arsc/chunk/xml/ResXmlDocumentTest.java
index bfa2aa710..854370eaf 100644
--- a/src/test/java/com/reandroid/arsc/chunk/xml/ResXmlDocumentTest.java
+++ b/src/test/java/com/reandroid/arsc/chunk/xml/ResXmlDocumentTest.java
@@ -142,6 +142,83 @@ public void testEncodeDecodeXml() throws XmlPullParserException, IOException {
decoded = decoded.replaceAll("\\s+", "");
Assert.assertEquals(org, decoded);
}
+
+ @Test
+ public void testIssue202AlternateAndroidNamespace()
+ throws Exception {
+
+ String xml =
+ "" +
+ "" +
+ "";
+
+ ResXmlDocument document = new ResXmlDocument();
+ document.setApkFile(createEmptyApkModule());
+ document.parse(XMLFactory.newPullParser(xml));
+
+ ResXmlElement root = document.getDocumentElement();
+ Assert.assertNotNull(root);
+
+ ResXmlAttribute version =
+ root.searchAttributeByName("versionCode");
+ Assert.assertNotNull(version);
+ Assert.assertEquals("http://schemas.android.com/apk/res/android", version.getUri());
+
+ ResXmlElement sdk = root.getElement("uses-sdk");
+ Assert.assertNotNull(sdk);
+ Assert.assertNotNull(
+ sdk.searchAttributeByName("targetSdkVersion"));
+
+ document.refreshFull();
+
+ StringWriter writer = new StringWriter();
+ XmlSerializer serializer = XMLFactory.newSerializer(writer);
+ document.serialize(serializer);
+
+ String output = writer.toString();
+ Assert.assertTrue(output.contains("733700004"));
+ Assert.assertTrue(output.contains("137.0.7337.0"));
+ }
+
+
+ @Test
+ public void testIssue202JsonNamespaceRoundTrip()
+ throws Exception {
+
+ String xml =
+ "";
+
+ ResXmlDocument original = new ResXmlDocument();
+ original.setApkFile(createEmptyApkModule());
+ original.parse(XMLFactory.newPullParser(xml));
+
+ com.reandroid.json.JSONObject json = original.toJson();
+
+ ResXmlDocument restored = new ResXmlDocument();
+ restored.setApkFile(createEmptyApkModule());
+ restored.fromJson(json);
+
+ ResXmlElement root = restored.getDocumentElement();
+ Assert.assertNotNull(root);
+
+ ResXmlAttribute version =
+ root.searchAttributeByName("versionCode");
+
+ Assert.assertNotNull(version);
+ Assert.assertEquals(
+ "http://schemas.android.com/apk/res/android",
+ version.getUri());
+ Assert.assertEquals(733700004, version.getData());
+ }
+
private static ApkModule createEmptyApkModule() throws IOException {
ApkModule apkModule = new ApkModule();
apkModule.setTableBlock(createEmptyTable());