Skip to content

Commit 4c71ecb

Browse files
committed
Accessing bin xml nodes with XMLPath
1 parent 56dc2a0 commit 4c71ecb

File tree

3 files changed

+109
-1
lines changed

3 files changed

+109
-1
lines changed

src/main/java/com/reandroid/arsc/chunk/xml/AndroidManifestBlock.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.reandroid.utils.collection.CollectionUtil;
2929
import com.reandroid.utils.collection.CombiningIterator;
3030
import com.reandroid.utils.collection.ComputeIterator;
31+
import com.reandroid.xml.XMLPath;
3132

3233
import java.io.File;
3334
import java.io.IOException;
@@ -45,6 +46,26 @@ public AndroidManifestBlock() {
4546
super();
4647
super.getStringPool().setUtf8(false);
4748
}
49+
50+
public ResXmlElement getOrCreateNamedElement(XMLPath xmlPath, String value) {
51+
ResXmlElement element = getNamedElement(xmlPath, value);
52+
if (element == null) {
53+
element = newChildElement(xmlPath);
54+
element.getOrCreateAndroidAttribute(NAME_name, ID_name)
55+
.setValueAsString(value);
56+
}
57+
return element;
58+
}
59+
public ResXmlElement getNamedElement(XMLPath xmlPath, String value) {
60+
Iterator<ResXmlElement> iterator = xmlPath.find(this);
61+
while (iterator.hasNext()) {
62+
ResXmlElement element = iterator.next();
63+
if (value.equals(getAndroidNameValue(element))) {
64+
return element;
65+
}
66+
}
67+
return null;
68+
}
4869
public ApkFile.ApkType guessApkType() {
4970
if (isSplit()) {
5071
return ApkFile.ApkType.SPLIT;

src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,24 @@
1010
import com.reandroid.json.JSONObject;
1111
import com.reandroid.utils.collection.CollectionUtil;
1212
import com.reandroid.utils.collection.CombiningIterator;
13+
import com.reandroid.utils.collection.ComputeIterator;
1314
import com.reandroid.utils.collection.IterableIterator;
1415
import com.reandroid.utils.collection.SingleIterator;
1516
import com.reandroid.utils.io.FileUtil;
1617
import com.reandroid.xml.XMLDocument;
1718
import com.reandroid.xml.XMLFactory;
19+
import com.reandroid.xml.XMLPath;
1820
import com.reandroid.xml.XMLUtil;
1921
import com.reandroid.xml.base.Document;
2022
import org.xmlpull.v1.XmlPullParser;
2123
import org.xmlpull.v1.XmlPullParserException;
2224
import org.xmlpull.v1.XmlSerializer;
2325

24-
import java.io.*;
26+
import java.io.File;
27+
import java.io.IOException;
28+
import java.io.InputStream;
29+
import java.io.OutputStream;
30+
import java.io.StringWriter;
2531
import java.util.Iterator;
2632

2733
public class ResXmlDocument extends ResXmlDocumentOrElement implements
@@ -96,6 +102,78 @@ private ResXmlDocument getParentDocument() {
96102
return getParentInstance(ResXmlDocument.class);
97103
}
98104

105+
public boolean removeAttributes(XMLPath xmlPath) {
106+
if (!xmlPath.isAttribute()) {
107+
throw new IllegalArgumentException("Path is not a type of attribute: " + xmlPath);
108+
}
109+
Iterator<ResXmlAttribute> iterator = xmlPath.findAll(getElements());
110+
iterator = CollectionUtil.copyOf(iterator);
111+
boolean result = false;
112+
while (iterator.hasNext()) {
113+
ResXmlAttribute attribute = iterator.next();
114+
attribute.removeSelf();
115+
result = true;
116+
}
117+
return result;
118+
}
119+
public boolean removeElements(XMLPath xmlPath) {
120+
Iterator<ResXmlElement> iterator;
121+
if (xmlPath.isAttribute()) {
122+
Iterator<ResXmlAttribute> attributes = xmlPath.findAll(getElements());
123+
iterator = ComputeIterator.of(attributes, ResXmlAttribute::getParentElement);
124+
} else {
125+
iterator = xmlPath.findAll(getElements());
126+
}
127+
iterator = CollectionUtil.copyOf(iterator);
128+
boolean result = false;
129+
while (iterator.hasNext()) {
130+
ResXmlElement element = iterator.next();
131+
element.removeSelf();
132+
result = true;
133+
}
134+
return result;
135+
}
136+
public ResXmlElement newChildElement(XMLPath xmlPath) {
137+
if (xmlPath.containsAnyPathOrName()) {
138+
throw new IllegalArgumentException("invalid path: " + xmlPath);
139+
}
140+
if (!xmlPath.isElement()) {
141+
return newChildElement(xmlPath.getParent());
142+
}
143+
String name = xmlPath.getName();
144+
XMLPath parent = xmlPath.getParent();
145+
if (parent != null) {
146+
return getOrCreateChildElement(parent)
147+
.newElement(name);
148+
}
149+
if (this instanceof ResXmlDocument) {
150+
return getOrCreateElement(name);
151+
}
152+
return newElement(name);
153+
}
154+
public ResXmlElement getOrCreateChildElement(XMLPath xmlPath) {
155+
if (xmlPath.containsAnyPathOrName()) {
156+
throw new IllegalArgumentException("invalid path: " + xmlPath);
157+
}
158+
if (!xmlPath.isElement()) {
159+
return newChildElement(xmlPath.getParent());
160+
}
161+
ResXmlElement element = null;
162+
int depth = xmlPath.depth();
163+
int i = depth;
164+
while (i >= 0) {
165+
XMLPath path = xmlPath.getPath(i);
166+
String name = path.getName();
167+
if (i == depth) {
168+
element = this.getOrCreateElement(name);
169+
} else {
170+
element = element.getOrCreateElement(name);
171+
}
172+
i --;
173+
}
174+
return element;
175+
}
176+
99177
@Override
100178
ResXmlDocumentChunk getChunk() {
101179
return (ResXmlDocumentChunk) super.getChunk();

src/main/java/com/reandroid/arsc/chunk/xml/ResXmlElement.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,15 @@ public ResXmlAttribute searchAttributeByResourceId(int resourceId) {
357357
public ResXmlAttribute searchAttribute(String namespace, String name) {
358358
return getAttributeArray().searchAttribute(namespace, name);
359359
}
360+
public boolean hasAttribute(int resourceId) {
361+
return getAttributeArray().searchAttributeByResourceId(resourceId) != null;
362+
}
363+
public boolean hasAttribute(String name) {
364+
return getAttributeArray().searchAttributeByName(name) != null;
365+
}
366+
public boolean hasAttribute(String namespace, String name) {
367+
return getAttributeArray().searchAttribute(namespace, name) != null;
368+
}
360369

361370
public ResXmlAttribute getIdAttribute() {
362371
return getStartElement().getIdAttributePosition().getAttribute();

0 commit comments

Comments
 (0)