mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-29 22:04:25 +02:00
better xml namespace handling
This commit is contained in:
parent
75d6ed704b
commit
b07b8bddfb
@ -211,8 +211,7 @@ public class ApkModuleXmlDecoder extends ApkDecoder implements Predicate<Entry>
|
|||||||
}
|
}
|
||||||
private void serializeXml(int currentPackageId, ResXmlDocument document, File outFile)
|
private void serializeXml(int currentPackageId, ResXmlDocument document, File outFile)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
XMLNamespaceValidator namespaceValidator = new XMLNamespaceValidator(document);
|
XMLNamespaceValidator.validateNamespaces(document);
|
||||||
namespaceValidator.validate();
|
|
||||||
ResXmlDocumentSerializer serializer = getDocumentSerializer();
|
ResXmlDocumentSerializer serializer = getDocumentSerializer();
|
||||||
if(currentPackageId != 0){
|
if(currentPackageId != 0){
|
||||||
serializer.getDecoder().setCurrentPackageId(currentPackageId);
|
serializer.getDecoder().setCurrentPackageId(currentPackageId);
|
||||||
|
@ -121,8 +121,7 @@ public class ResXmlDocumentSerializer implements ResXmlPullParser.DocumentLoaded
|
|||||||
if(!validateXmlNamespace){
|
if(!validateXmlNamespace){
|
||||||
return resXmlDocument;
|
return resXmlDocument;
|
||||||
}
|
}
|
||||||
XMLNamespaceValidator namespaceValidator = new XMLNamespaceValidator(resXmlDocument);
|
XMLNamespaceValidator.validateNamespaces(resXmlDocument);
|
||||||
namespaceValidator.validate();
|
|
||||||
return resXmlDocument;
|
return resXmlDocument;
|
||||||
}
|
}
|
||||||
private IOException getError(Exception exception){
|
private IOException getError(Exception exception){
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -17,54 +17,65 @@ package com.reandroid.apk.xmldecoder;
|
|||||||
|
|
||||||
import com.reandroid.arsc.chunk.xml.*;
|
import com.reandroid.arsc.chunk.xml.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class XMLNamespaceValidator {
|
public class XMLNamespaceValidator {
|
||||||
private static final String URI_ANDROID="http://schemas.android.com/apk/res/android";
|
private static final String URI_ANDROID = "http://schemas.android.com/apk/res/android";
|
||||||
private static final String URI_APP="http://schemas.android.com/apk/res-auto";
|
private static final String URI_APP = "http://schemas.android.com/apk/res-auto";
|
||||||
private static final String PREFIX_ANDROID ="android";
|
private static final String PREFIX_ANDROID = "android";
|
||||||
private static final String PREFIX_APP="app";
|
private static final String PREFIX_APP = "app";
|
||||||
private final ResXmlDocument xmlBlock;
|
private final ResXmlDocument xmlBlock;
|
||||||
private List<ResXmlAttribute> mAttributeList;
|
|
||||||
private ResXmlElement mRootElement;
|
|
||||||
private ResXmlStartNamespace mNsAndroid;
|
|
||||||
private ResXmlStartNamespace mNsApp;
|
|
||||||
public XMLNamespaceValidator(ResXmlDocument xmlBlock){
|
public XMLNamespaceValidator(ResXmlDocument xmlBlock){
|
||||||
this.xmlBlock=xmlBlock;
|
this.xmlBlock=xmlBlock;
|
||||||
}
|
}
|
||||||
public void validate(){
|
public void validate(){
|
||||||
if(getRootElement()==null){
|
validateNamespaces(xmlBlock);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
for(ResXmlAttribute attribute:getAttributes()){
|
|
||||||
validate(attribute);
|
public static boolean isValid(ResXmlAttribute attribute){
|
||||||
|
int resourceId = attribute.getNameResourceID();
|
||||||
|
if(resourceId == 0){
|
||||||
|
return attribute.getUri() == null;
|
||||||
}
|
}
|
||||||
}
|
if(isAndroid(toPackageId(resourceId))){
|
||||||
private void validate(ResXmlAttribute attribute){
|
return isValidAndroidNamespace(attribute);
|
||||||
int resourceId=attribute.getNameResourceID();
|
|
||||||
if(resourceId==0){
|
|
||||||
removeNamespace(attribute);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int pkgId=toPackageId(resourceId);
|
|
||||||
if(isAndroid(pkgId)){
|
|
||||||
setAndroidNamespace(attribute);
|
|
||||||
}else {
|
}else {
|
||||||
setAppNamespace(attribute);
|
return isValidAppNamespace(attribute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void removeNamespace(ResXmlAttribute attribute){
|
public static void validateNamespaces(ResXmlDocument resXmlDocument){
|
||||||
|
validateNamespaces(resXmlDocument.getResXmlElement());
|
||||||
|
}
|
||||||
|
public static void validateNamespaces(ResXmlElement element){
|
||||||
|
validateNamespaces(element.listAttributes());
|
||||||
|
for(ResXmlElement child : element.listElements()){
|
||||||
|
validateNamespaces(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateNamespaces(Collection<ResXmlAttribute> attributeList){
|
||||||
|
for(ResXmlAttribute attribute : attributeList){
|
||||||
|
validateNamespace(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void validateNamespace(ResXmlAttribute attribute){
|
||||||
|
int resourceId = attribute.getNameResourceID();
|
||||||
|
if(resourceId == 0){
|
||||||
attribute.setNamespaceReference(-1);
|
attribute.setNamespaceReference(-1);
|
||||||
}
|
|
||||||
private void setAppNamespace(ResXmlAttribute attribute){
|
|
||||||
if(isValidAppNamespace(attribute)){
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ResXmlStartNamespace ns = getOrCreateApp();
|
if(isAndroid(toPackageId(resourceId))){
|
||||||
attribute.setNamespaceReference(ns.getUriReference());
|
if(!isValidAndroidNamespace(attribute)){
|
||||||
|
attribute.setNamespace(URI_ANDROID, PREFIX_ANDROID);
|
||||||
}
|
}
|
||||||
private boolean isValidAppNamespace(ResXmlAttribute attribute){
|
}else {
|
||||||
|
if(!isValidAppNamespace(attribute)){
|
||||||
|
attribute.setNamespace(URI_APP, PREFIX_APP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isValidAppNamespace(ResXmlAttribute attribute){
|
||||||
String uri = attribute.getUri();
|
String uri = attribute.getUri();
|
||||||
String prefix = attribute.getNamePrefix();
|
String prefix = attribute.getNamePrefix();
|
||||||
if(URI_ANDROID.equals(uri) || PREFIX_ANDROID.equals(prefix)){
|
if(URI_ANDROID.equals(uri) || PREFIX_ANDROID.equals(prefix)){
|
||||||
@ -75,62 +86,15 @@ public class XMLNamespaceValidator {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
private void setAndroidNamespace(ResXmlAttribute attribute){
|
private static boolean isValidAndroidNamespace(ResXmlAttribute attribute){
|
||||||
if(URI_ANDROID.equals(attribute.getUri())
|
return URI_ANDROID.equals(attribute.getUri())
|
||||||
&& PREFIX_ANDROID.equals(attribute.getNamePrefix())){
|
&& PREFIX_ANDROID.equals(attribute.getNamePrefix());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
ResXmlStartNamespace ns = getOrCreateAndroid();
|
|
||||||
attribute.setNamespaceReference(ns.getUriReference());
|
private static boolean isAndroid(int pkgId){
|
||||||
}
|
|
||||||
private ResXmlStartNamespace getOrCreateApp(){
|
|
||||||
if(mNsApp !=null){
|
|
||||||
return mNsApp;
|
|
||||||
}
|
|
||||||
ResXmlElement root=getRootElement();
|
|
||||||
ResXmlStartNamespace ns = root.getOrCreateNamespace(URI_APP, PREFIX_APP);
|
|
||||||
String prefix=ns.getPrefix();
|
|
||||||
if(PREFIX_ANDROID.equals(prefix) || isEmpty(prefix)){
|
|
||||||
ns.setPrefix(PREFIX_APP);
|
|
||||||
}
|
|
||||||
mNsApp = ns;
|
|
||||||
return mNsApp;
|
|
||||||
}
|
|
||||||
private ResXmlStartNamespace getOrCreateAndroid(){
|
|
||||||
if(mNsAndroid !=null){
|
|
||||||
return mNsAndroid;
|
|
||||||
}
|
|
||||||
ResXmlElement root=getRootElement();
|
|
||||||
ResXmlStartNamespace ns = root.getOrCreateNamespace(URI_ANDROID, PREFIX_ANDROID);
|
|
||||||
if(!PREFIX_ANDROID.equals(ns.getPrefix())){
|
|
||||||
ns.setPrefix(PREFIX_ANDROID);
|
|
||||||
}
|
|
||||||
mNsAndroid =ns;
|
|
||||||
return mNsAndroid;
|
|
||||||
}
|
|
||||||
private ResXmlElement getRootElement() {
|
|
||||||
if(mRootElement==null){
|
|
||||||
mRootElement = xmlBlock.getResXmlElement();
|
|
||||||
}
|
|
||||||
return mRootElement;
|
|
||||||
}
|
|
||||||
private List<ResXmlAttribute> getAttributes(){
|
|
||||||
if(mAttributeList==null){
|
|
||||||
mAttributeList=listAttributes(xmlBlock.getResXmlElement());
|
|
||||||
}
|
|
||||||
return mAttributeList;
|
|
||||||
}
|
|
||||||
private List<ResXmlAttribute> listAttributes(ResXmlElement element){
|
|
||||||
List<ResXmlAttribute> results = new ArrayList<>(element.listAttributes());
|
|
||||||
for(ResXmlElement child:element.listElements()){
|
|
||||||
results.addAll(listAttributes(child));
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
private boolean isAndroid(int pkgId){
|
|
||||||
return pkgId==1;
|
return pkgId==1;
|
||||||
}
|
}
|
||||||
private int toPackageId(int resId){
|
private static int toPackageId(int resId){
|
||||||
return (resId >> 24 & 0xFF);
|
return (resId >> 24 & 0xFF);
|
||||||
}
|
}
|
||||||
private static boolean isEmpty(String str){
|
private static boolean isEmpty(String str){
|
||||||
|
@ -184,6 +184,18 @@ public class ResXmlAttribute extends ValueItem implements AttributeValue, Compar
|
|||||||
int getNamespaceReference(){
|
int getNamespaceReference(){
|
||||||
return getInteger(getBytesInternal(), OFFSET_NS);
|
return getInteger(getBytesInternal(), OFFSET_NS);
|
||||||
}
|
}
|
||||||
|
public void setNamespace(String uri, String prefix){
|
||||||
|
if(uri == null || prefix == null){
|
||||||
|
setNamespaceReference(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResXmlElement parentElement = getParentResXmlElement();
|
||||||
|
if(parentElement == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResXmlStartNamespace ns = parentElement.getOrCreateNamespace(uri, prefix);
|
||||||
|
setNamespaceReference(ns.getUriReference());
|
||||||
|
}
|
||||||
public void setNamespaceReference(int ref){
|
public void setNamespaceReference(int ref){
|
||||||
if(ref == getNamespaceReference()){
|
if(ref == getNamespaceReference()){
|
||||||
return;
|
return;
|
||||||
|
@ -110,7 +110,7 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public String getEndComment(){
|
String getEndComment(){
|
||||||
ResXmlEndElement end = getEndElement();
|
ResXmlEndElement end = getEndElement();
|
||||||
if(end!=null){
|
if(end!=null){
|
||||||
return end.getComment();
|
return end.getComment();
|
||||||
@ -143,36 +143,30 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
public ResXmlAttribute newAttribute(){
|
public ResXmlAttribute newAttribute(){
|
||||||
return getStartElement().newAttribute();
|
return getStartElement().newAttribute();
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
void onRemoved(){
|
void onRemoved(){
|
||||||
for(ResXmlStartNamespace startNamespace:getStartNamespaceList()){
|
for(ResXmlStartNamespace startNamespace:getStartNamespaceList()){
|
||||||
startNamespace.onRemoved();
|
startNamespace.onRemoved();
|
||||||
}
|
}
|
||||||
ResXmlStartElement start = getStartElement();
|
ResXmlStartElement start = getStartElement();
|
||||||
if(start!=null){
|
if(start != null){
|
||||||
start.onRemoved();
|
start.onRemoved();
|
||||||
}
|
}
|
||||||
ResXmlText resXmlText=getResXmlText();
|
for(ResXmlNode xmlNode : listXmlNodes()){
|
||||||
if(resXmlText!=null){
|
xmlNode.onRemoved();
|
||||||
resXmlText.onRemoved();
|
|
||||||
}
|
|
||||||
for(ResXmlElement child:listElements()){
|
|
||||||
child.onRemoved();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
void linkStringReferences(){
|
void linkStringReferences(){
|
||||||
for(ResXmlStartNamespace startNamespace:getStartNamespaceList()){
|
for(ResXmlStartNamespace startNamespace:getStartNamespaceList()){
|
||||||
startNamespace.linkStringReferences();
|
startNamespace.linkStringReferences();
|
||||||
}
|
}
|
||||||
ResXmlStartElement start = getStartElement();
|
ResXmlStartElement start = getStartElement();
|
||||||
if(start!=null){
|
if(start != null){
|
||||||
start.linkStringReferences();
|
start.linkStringReferences();
|
||||||
}
|
}
|
||||||
ResXmlText resXmlText=getResXmlText();
|
for(ResXmlNode xmlNode : getXmlNodes()){
|
||||||
if(resXmlText!=null){
|
xmlNode.linkStringReferences();
|
||||||
resXmlText.linkStringReferences();
|
|
||||||
}
|
|
||||||
for(ResXmlElement child:listElements()){
|
|
||||||
child.linkStringReferences();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public ResXmlElement createChildElement(){
|
public ResXmlElement createChildElement(){
|
||||||
@ -355,13 +349,11 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDepth(){
|
public int getDepth(){
|
||||||
int depth = 0;
|
|
||||||
ResXmlElement parent = getParentResXmlElement();
|
ResXmlElement parent = getParentResXmlElement();
|
||||||
while (parent!=null){
|
if(parent != null){
|
||||||
depth++;
|
return parent.getDepth() + 1;
|
||||||
parent = parent.getParentResXmlElement();
|
|
||||||
}
|
}
|
||||||
return depth;
|
return 0;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void addEvents(ParserEventList parserEventList){
|
void addEvents(ParserEventList parserEventList){
|
||||||
@ -423,7 +415,7 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
if(xmlNode==null){
|
if(xmlNode==null){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
xmlNode.onRemove();
|
xmlNode.onRemoved();
|
||||||
mBody.remove(xmlNode);
|
mBody.remove(xmlNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,6 +425,22 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
public int countResXmlNodes(){
|
public int countResXmlNodes(){
|
||||||
return mBody.size();
|
return mBody.size();
|
||||||
}
|
}
|
||||||
|
public boolean hasText(){
|
||||||
|
for(ResXmlNode xmlNode : getXmlNodes()){
|
||||||
|
if(xmlNode instanceof ResXmlTextNode){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public boolean hasElement(){
|
||||||
|
for(ResXmlNode xmlNode : getXmlNodes()){
|
||||||
|
if(xmlNode instanceof ResXmlElement){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
public List<ResXmlNode> listXmlNodes(){
|
public List<ResXmlNode> listXmlNodes(){
|
||||||
return new ArrayList<>(getXmlNodes());
|
return new ArrayList<>(getXmlNodes());
|
||||||
}
|
}
|
||||||
@ -479,8 +487,8 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
public ResXmlElement getRootResXmlElement(){
|
public ResXmlElement getRootResXmlElement(){
|
||||||
ResXmlElement parent=getParentResXmlElement();
|
ResXmlElement parent = getParentResXmlElement();
|
||||||
if(parent!=null){
|
if(parent != null){
|
||||||
return parent.getRootResXmlElement();
|
return parent.getRootResXmlElement();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
@ -503,13 +511,31 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
public ResXmlStartNamespace getNamespace(String uri, String prefix){
|
||||||
|
if(uri == null || prefix == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for(ResXmlStartNamespace ns : mStartNamespaceList.getChildes()){
|
||||||
|
if(uri.equals(ns.getUri()) && prefix.equals(ns.getPrefix())){
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResXmlElement xmlElement = getParentResXmlElement();
|
||||||
|
if(xmlElement != null){
|
||||||
|
return xmlElement.getNamespace(uri, prefix);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public ResXmlStartNamespace getOrCreateNamespace(String uri, String prefix){
|
public ResXmlStartNamespace getOrCreateNamespace(String uri, String prefix){
|
||||||
ResXmlStartNamespace exist=getStartNamespaceByUri(uri);
|
ResXmlStartNamespace exist = getNamespace(uri, prefix);
|
||||||
if(exist!=null){
|
if(exist != null){
|
||||||
return exist;
|
return exist;
|
||||||
}
|
}
|
||||||
ResXmlStartNamespace startNamespace=new ResXmlStartNamespace();
|
return getRootResXmlElement().createNamespace(uri, prefix);
|
||||||
ResXmlEndNamespace endNamespace=new ResXmlEndNamespace();
|
}
|
||||||
|
public ResXmlStartNamespace createNamespace(String uri, String prefix){
|
||||||
|
ResXmlStartNamespace startNamespace = new ResXmlStartNamespace();
|
||||||
|
ResXmlEndNamespace endNamespace = new ResXmlEndNamespace();
|
||||||
startNamespace.setEnd(endNamespace);
|
startNamespace.setEnd(endNamespace);
|
||||||
|
|
||||||
addStartNamespace(startNamespace);
|
addStartNamespace(startNamespace);
|
||||||
@ -562,7 +588,7 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
public void addStartNamespace(ResXmlStartNamespace item){
|
public void addStartNamespace(ResXmlStartNamespace item){
|
||||||
mStartNamespaceList.add(item);
|
mStartNamespaceList.add(item);
|
||||||
}
|
}
|
||||||
public List<ResXmlEndNamespace> getEndNamespaceList(){
|
private List<ResXmlEndNamespace> getEndNamespaceList(){
|
||||||
return mEndNamespaceList.getChildes();
|
return mEndNamespaceList.getChildes();
|
||||||
}
|
}
|
||||||
public void addEndNamespace(ResXmlEndNamespace item){
|
public void addEndNamespace(ResXmlEndNamespace item){
|
||||||
@ -596,26 +622,17 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
public ResXmlStartElement getStartElement(){
|
public ResXmlStartElement getStartElement(){
|
||||||
return mStartElementContainer.getItem();
|
return mStartElementContainer.getItem();
|
||||||
}
|
}
|
||||||
public void setStartElement(ResXmlStartElement item){
|
private void setStartElement(ResXmlStartElement item){
|
||||||
mStartElementContainer.setItem(item);
|
mStartElementContainer.setItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResXmlEndElement getEndElement(){
|
private ResXmlEndElement getEndElement(){
|
||||||
return mEndElementContainer.getItem();
|
return mEndElementContainer.getItem();
|
||||||
}
|
}
|
||||||
public void setEndElement(ResXmlEndElement item){
|
private void setEndElement(ResXmlEndElement item){
|
||||||
mEndElementContainer.setItem(item);
|
mEndElementContainer.setItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use listXmlText() instead to be removed on next version
|
|
||||||
@Deprecated
|
|
||||||
public ResXmlText getResXmlText(){
|
|
||||||
List<ResXmlText> xmlTextList=listXmlText();
|
|
||||||
if(xmlTextList.size()==0){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return xmlTextList.get(0);
|
|
||||||
}
|
|
||||||
public void addResXmlTextNode(ResXmlTextNode xmlTextNode){
|
public void addResXmlTextNode(ResXmlTextNode xmlTextNode){
|
||||||
mBody.add(xmlTextNode);
|
mBody.add(xmlTextNode);
|
||||||
}
|
}
|
||||||
@ -624,16 +641,6 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
addResXmlTextNode(new ResXmlTextNode(xmlText));
|
addResXmlTextNode(new ResXmlTextNode(xmlText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Use addResXmlText()
|
|
||||||
@Deprecated
|
|
||||||
public void setResXmlText(ResXmlText xmlText){
|
|
||||||
addResXmlText(xmlText);
|
|
||||||
}
|
|
||||||
@Deprecated
|
|
||||||
public void setResXmlText(String text){
|
|
||||||
clearChildes();
|
|
||||||
addResXmlText(text);
|
|
||||||
}
|
|
||||||
public void addResXmlText(String text){
|
public void addResXmlText(String text){
|
||||||
if(text==null){
|
if(text==null){
|
||||||
return;
|
return;
|
||||||
@ -995,13 +1002,14 @@ public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject>
|
|||||||
public String toString(){
|
public String toString(){
|
||||||
ResXmlStartElement start = getStartElement();
|
ResXmlStartElement start = getStartElement();
|
||||||
if(start!=null){
|
if(start!=null){
|
||||||
ResXmlText text=getResXmlText();
|
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append("<");
|
builder.append("<");
|
||||||
builder.append(start.toString());
|
builder.append(start.toString());
|
||||||
if(text!=null){
|
if(hasText() && !hasElement()){
|
||||||
builder.append(">");
|
builder.append(">");
|
||||||
builder.append(text.toString());
|
for(ResXmlText xmlText : listXmlText()){
|
||||||
|
builder.append(xmlText.getText());
|
||||||
|
}
|
||||||
builder.append("</");
|
builder.append("</");
|
||||||
builder.append(start.getTagName());
|
builder.append(start.getTagName());
|
||||||
builder.append(">");
|
builder.append(">");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -23,10 +23,10 @@ public abstract class ResXmlNode extends FixedBlockContainer implements JSONCon
|
|||||||
ResXmlNode(int childesCount) {
|
ResXmlNode(int childesCount) {
|
||||||
super(childesCount);
|
super(childesCount);
|
||||||
}
|
}
|
||||||
void onRemove(){
|
abstract void onRemoved();
|
||||||
}
|
abstract void linkStringReferences();
|
||||||
public abstract int getDepth();
|
public abstract int getDepth();
|
||||||
abstract void addEvents(ParserEventList parserEventList);
|
abstract void addEvents(ParserEventList parserEventList);
|
||||||
|
|
||||||
public static final String NAME_node_type="node_type";
|
public static final String NAME_node_type = "node_type";
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -75,6 +75,14 @@ public class ResXmlTextNode extends ResXmlNode {
|
|||||||
getResXmlText().setTextReference(ref);
|
getResXmlText().setTextReference(ref);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
void onRemoved(){
|
||||||
|
getResXmlText().onRemoved();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
void linkStringReferences(){
|
||||||
|
getResXmlText().linkStringReferences();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
String txt=getText();
|
String txt=getText();
|
||||||
if(txt!=null){
|
if(txt!=null){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user