mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-14 20:37:05 +02:00
fix: encode/decode XML styled strings properly
This commit is contained in:
parent
ee5db344af
commit
a5d71a28a4
@ -25,6 +25,7 @@ import com.reandroid.lib.arsc.chunk.xml.AndroidManifestBlock;
|
|||||||
import com.reandroid.lib.arsc.chunk.xml.ResXmlBlock;
|
import com.reandroid.lib.arsc.chunk.xml.ResXmlBlock;
|
||||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||||
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||||
|
import com.reandroid.lib.arsc.item.TableString;
|
||||||
import com.reandroid.lib.arsc.value.*;
|
import com.reandroid.lib.arsc.value.*;
|
||||||
import com.reandroid.lib.common.EntryStore;
|
import com.reandroid.lib.common.EntryStore;
|
||||||
import com.reandroid.lib.common.Frameworks;
|
import com.reandroid.lib.common.Frameworks;
|
||||||
@ -238,18 +239,17 @@ import java.util.*;
|
|||||||
attribute.setNameId(resourceId);
|
attribute.setNameId(resourceId);
|
||||||
element.setResourceId(resourceId);
|
element.setResourceId(resourceId);
|
||||||
if(!entryBlock.isEntryTypeBag()){
|
if(!entryBlock.isEntryTypeBag()){
|
||||||
String value;
|
|
||||||
ResValueInt resValueInt=(ResValueInt) entryBlock.getResValue();
|
ResValueInt resValueInt=(ResValueInt) entryBlock.getResValue();
|
||||||
if(resValueInt.getValueType()== ValueType.STRING){
|
if(resValueInt.getValueType()== ValueType.STRING){
|
||||||
value=ValueDecoder.escapeSpecialCharacter(
|
XmlHelper.setTextContent(element,
|
||||||
resValueInt.getValueAsString());
|
resValueInt.getValueAsPoolString());
|
||||||
}else {
|
}else {
|
||||||
value= ValueDecoder.decodeEntryValue(entryStore,
|
String value = ValueDecoder.decodeEntryValue(entryStore,
|
||||||
entryBlock.getPackageBlock(),
|
entryBlock.getPackageBlock(),
|
||||||
resValueInt.getValueType(),
|
resValueInt.getValueType(),
|
||||||
resValueInt.getData());
|
resValueInt.getData());
|
||||||
}
|
|
||||||
element.setTextContent(value);
|
element.setTextContent(value);
|
||||||
|
}
|
||||||
}else {
|
}else {
|
||||||
ResValueBag resValueBag=(ResValueBag) entryBlock.getResValue();
|
ResValueBag resValueBag=(ResValueBag) entryBlock.getResValue();
|
||||||
xmlBagDecoder.decode(resValueBag, element);
|
xmlBagDecoder.decode(resValueBag, element);
|
||||||
|
33
src/main/java/com/reandroid/lib/apk/XmlHelper.java
Normal file
33
src/main/java/com/reandroid/lib/apk/XmlHelper.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.reandroid.lib.apk;
|
||||||
|
|
||||||
|
import com.reandroid.lib.arsc.item.StringItem;
|
||||||
|
import com.reandroid.xml.XMLElement;
|
||||||
|
|
||||||
|
public class XmlHelper {
|
||||||
|
public static void setTextContent(XMLElement element, StringItem stringItem){
|
||||||
|
if(stringItem==null){
|
||||||
|
element.clearChildNodes();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!stringItem.hasStyle()){
|
||||||
|
element.setTextContent(stringItem.get());
|
||||||
|
}else {
|
||||||
|
element.setSpannableText(stringItem.getHtml());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.lib.apk.xmldecoder;
|
package com.reandroid.lib.apk.xmldecoder;
|
||||||
|
|
||||||
import com.reandroid.lib.apk.ApkUtil;
|
import com.reandroid.lib.apk.ApkUtil;
|
||||||
|
import com.reandroid.lib.apk.XmlHelper;
|
||||||
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.lib.arsc.value.ResValueBag;
|
import com.reandroid.lib.arsc.value.ResValueBag;
|
||||||
import com.reandroid.lib.arsc.value.ResValueBagItem;
|
import com.reandroid.lib.arsc.value.ResValueBagItem;
|
||||||
@ -38,11 +39,16 @@ import java.util.Set;
|
|||||||
Set<ValueType> valueTypes = new HashSet<>();
|
Set<ValueType> valueTypes = new HashSet<>();
|
||||||
for(int i=0;i<bagItems.length;i++){
|
for(int i=0;i<bagItems.length;i++){
|
||||||
ResValueBagItem bagItem = bagItems[i];
|
ResValueBagItem bagItem = bagItems[i];
|
||||||
String value = ValueDecoder.decodeIntEntry(entryStore, bagItem);
|
ValueType valueType = bagItem.getValueType();
|
||||||
XMLElement child = new XMLElement("item");
|
XMLElement child = new XMLElement("item");
|
||||||
|
if(valueType == ValueType.STRING){
|
||||||
|
XmlHelper.setTextContent(child, bagItem.getValueAsPoolString());
|
||||||
|
}else {
|
||||||
|
String value = ValueDecoder.decodeIntEntry(entryStore, bagItem);
|
||||||
child.setTextContent(value);
|
child.setTextContent(value);
|
||||||
|
}
|
||||||
parentElement.addChild(child);
|
parentElement.addChild(child);
|
||||||
valueTypes.add(bagItem.getValueType());
|
valueTypes.add(valueType);
|
||||||
}
|
}
|
||||||
if(valueTypes.contains(ValueType.STRING)){
|
if(valueTypes.contains(ValueType.STRING)){
|
||||||
parentElement.setTagName(ApkUtil.TAG_STRING_ARRAY);
|
parentElement.setTagName(ApkUtil.TAG_STRING_ARRAY);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.lib.apk.xmldecoder;
|
package com.reandroid.lib.apk.xmldecoder;
|
||||||
|
|
||||||
|
import com.reandroid.lib.apk.XmlHelper;
|
||||||
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.lib.arsc.value.ResValueBag;
|
import com.reandroid.lib.arsc.value.ResValueBag;
|
||||||
@ -57,11 +58,14 @@ class XMLCommonBagDecoder extends BagDecoder{
|
|||||||
|
|
||||||
child.setAttribute("name", name);
|
child.setAttribute("name", name);
|
||||||
|
|
||||||
|
ValueType valueType = item.getValueType();
|
||||||
|
if(valueType == ValueType.STRING){
|
||||||
|
XmlHelper.setTextContent(child, item.getValueAsPoolString());
|
||||||
|
}else {
|
||||||
String value = ValueDecoder.decode(entryStore, currentPackageId,
|
String value = ValueDecoder.decode(entryStore, currentPackageId,
|
||||||
resourceId, item.getValueType(), item.getData());
|
resourceId, item.getValueType(), item.getData());
|
||||||
|
|
||||||
child.setTextContent(value);
|
child.setTextContent(value);
|
||||||
|
}
|
||||||
parentElement.addChild(child);
|
parentElement.addChild(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.lib.apk.xmldecoder;
|
package com.reandroid.lib.apk.xmldecoder;
|
||||||
|
|
||||||
|
import com.reandroid.lib.apk.XmlHelper;
|
||||||
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.lib.arsc.value.BaseResValue;
|
import com.reandroid.lib.arsc.value.BaseResValue;
|
||||||
import com.reandroid.lib.arsc.value.ResValueBag;
|
import com.reandroid.lib.arsc.value.ResValueBag;
|
||||||
import com.reandroid.lib.arsc.value.ResValueBagItem;
|
import com.reandroid.lib.arsc.value.ResValueBagItem;
|
||||||
|
import com.reandroid.lib.arsc.value.ValueType;
|
||||||
import com.reandroid.lib.arsc.value.plurals.PluralsQuantity;
|
import com.reandroid.lib.arsc.value.plurals.PluralsQuantity;
|
||||||
import com.reandroid.lib.common.EntryStore;
|
import com.reandroid.lib.common.EntryStore;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
@ -36,11 +38,15 @@ class XMLPluralsDecoder extends BagDecoder{
|
|||||||
ResValueBagItem item = bagItems[i];
|
ResValueBagItem item = bagItems[i];
|
||||||
|
|
||||||
PluralsQuantity quantity = PluralsQuantity.valueOf(item.getIdLow());
|
PluralsQuantity quantity = PluralsQuantity.valueOf(item.getIdLow());
|
||||||
|
|
||||||
String value = ValueDecoder.decodeIntEntry(entryStore, item);
|
|
||||||
XMLElement child=new XMLElement("item");
|
XMLElement child=new XMLElement("item");
|
||||||
child.setAttribute("quantity", quantity.toString());
|
child.setAttribute("quantity", quantity.toString());
|
||||||
|
|
||||||
|
if(item.getValueType() == ValueType.STRING){
|
||||||
|
XmlHelper.setTextContent(child, item.getValueAsPoolString());
|
||||||
|
}else {
|
||||||
|
String value = ValueDecoder.decodeIntEntry(entryStore, item);
|
||||||
child.setTextContent(value);
|
child.setTextContent(value);
|
||||||
|
}
|
||||||
|
|
||||||
parentElement.addChild(child);
|
parentElement.addChild(child);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.lib.apk.xmlencoder;
|
package com.reandroid.lib.apk.xmlencoder;
|
||||||
|
|
||||||
|
import com.reandroid.lib.apk.ApkUtil;
|
||||||
import com.reandroid.xml.XMLDocument;
|
import com.reandroid.xml.XMLDocument;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
import com.reandroid.xml.XMLException;
|
import com.reandroid.xml.XMLException;
|
||||||
@ -85,6 +86,9 @@ class ValuesEncoder {
|
|||||||
if(type.startsWith("plurals")){
|
if(type.startsWith("plurals")){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if(type.startsWith("array")){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if(type.startsWith("string")){
|
if(type.startsWith("string")){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -108,7 +112,13 @@ class ValuesEncoder {
|
|||||||
if(type==null){
|
if(type==null){
|
||||||
type=first.getTagName();
|
type=first.getTagName();
|
||||||
}
|
}
|
||||||
if(type==null||type.equals("item")){
|
if(type==null){
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if(type.endsWith("-array")){
|
||||||
|
return "array";
|
||||||
|
}
|
||||||
|
if(type.equals("item")){
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
|
@ -30,8 +30,10 @@ import java.util.*;
|
|||||||
|
|
||||||
public class ValuesStringPoolBuilder {
|
public class ValuesStringPoolBuilder {
|
||||||
private final Set<String> stringList;
|
private final Set<String> stringList;
|
||||||
|
private final Set<String> styleList;
|
||||||
public ValuesStringPoolBuilder(){
|
public ValuesStringPoolBuilder(){
|
||||||
this.stringList=new HashSet<>();
|
this.stringList=new HashSet<>();
|
||||||
|
this.styleList=new HashSet<>();
|
||||||
}
|
}
|
||||||
public void addTo(TableStringPool stringPool){
|
public void addTo(TableStringPool stringPool){
|
||||||
if(stringPool.getStringsArray().childesCount()==0){
|
if(stringPool.getStringsArray().childesCount()==0){
|
||||||
@ -39,6 +41,7 @@ import java.util.*;
|
|||||||
}
|
}
|
||||||
stringPool.addStrings(stringList);
|
stringPool.addStrings(stringList);
|
||||||
stringList.clear();
|
stringList.clear();
|
||||||
|
styleList.clear();
|
||||||
stringPool.refresh();
|
stringPool.refresh();
|
||||||
}
|
}
|
||||||
private void buildWithStyles(TableStringPool stringPool){
|
private void buildWithStyles(TableStringPool stringPool){
|
||||||
@ -74,11 +77,13 @@ import java.util.*;
|
|||||||
private List<XMLSpannable> buildSpannable(){
|
private List<XMLSpannable> buildSpannable(){
|
||||||
List<XMLSpannable> results=new ArrayList<>();
|
List<XMLSpannable> results=new ArrayList<>();
|
||||||
Set<String> removeList=new HashSet<>();
|
Set<String> removeList=new HashSet<>();
|
||||||
for(String text:stringList){
|
for(String text:styleList){
|
||||||
XMLSpannable spannable=XMLSpannable.parse(text);
|
XMLSpannable spannable=XMLSpannable.parse(text);
|
||||||
if(spannable!=null){
|
if(spannable!=null){
|
||||||
results.add(spannable);
|
results.add(spannable);
|
||||||
removeList.add(text);
|
removeList.add(text);
|
||||||
|
}else {
|
||||||
|
stringList.add(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stringList.removeAll(removeList);
|
stringList.removeAll(removeList);
|
||||||
@ -143,14 +148,21 @@ import java.util.*;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void addStrings(XMLElement element){
|
private void addStrings(XMLElement element){
|
||||||
|
if(element.hasChildElements()){
|
||||||
|
addStyleElement(element);
|
||||||
|
}else {
|
||||||
String text = ValueDecoder
|
String text = ValueDecoder
|
||||||
.unEscapeSpecialCharacter(element.getTextContent());
|
.unEscapeSpecialCharacter(element.getTextContent());
|
||||||
addString(text);
|
addString(text);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private void addString(String text){
|
private void addString(String text){
|
||||||
if(text!=null && text.length()>0 && text.charAt(0)!='@'){
|
if(text!=null && text.length()>0 && text.charAt(0)!='@'){
|
||||||
stringList.add(text);
|
stringList.add(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void addStyleElement(XMLElement element){
|
||||||
|
styleList.add(element.buildTextContent());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,10 @@ public abstract class BaseResValueItem extends BaseResValue implements ResValueI
|
|||||||
BaseResValueItem(int bytesLength) {
|
BaseResValueItem(int bytesLength) {
|
||||||
super(bytesLength);
|
super(bytesLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TableString getValueAsPoolString(){
|
||||||
|
return getTableString(getData());
|
||||||
|
}
|
||||||
String getString(int ref){
|
String getString(int ref){
|
||||||
TableString tableString=getTableString(ref);
|
TableString tableString=getTableString(ref);
|
||||||
if(tableString==null){
|
if(tableString==null){
|
||||||
|
@ -62,6 +62,9 @@ public class XMLComment extends XMLElement {
|
|||||||
return XMLUtil.isEmpty(getTextContent());
|
return XMLUtil.isEmpty(getTextContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void buildTextContent(Writer writer) throws IOException{
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean write(Writer writer, boolean newLineAttributes) throws IOException {
|
public boolean write(Writer writer, boolean newLineAttributes) throws IOException {
|
||||||
if(isHidden()){
|
if(isHidden()){
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
package com.reandroid.xml;
|
package com.reandroid.xml;
|
||||||
|
|
||||||
|
|
||||||
|
import com.reandroid.xml.parser.XMLSpanParser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
@ -26,7 +28,7 @@ public class XMLElement extends XMLNode{
|
|||||||
private String mTagName;
|
private String mTagName;
|
||||||
private final List<XMLAttribute> mAttributes = new ArrayList<>();
|
private final List<XMLAttribute> mAttributes = new ArrayList<>();
|
||||||
private final List<XMLElement> mChildElements = new ArrayList<>();
|
private final List<XMLElement> mChildElements = new ArrayList<>();
|
||||||
private List<XMLComment> mComments;
|
private final List<XMLComment> mComments = new ArrayList<>();
|
||||||
private final List<XMLText> mTexts = new ArrayList<>();
|
private final List<XMLText> mTexts = new ArrayList<>();
|
||||||
private XMLElement mParent;
|
private XMLElement mParent;
|
||||||
private int mIndent;
|
private int mIndent;
|
||||||
@ -196,7 +198,7 @@ public class XMLElement extends XMLNode{
|
|||||||
mTexts.clear();
|
mTexts.clear();
|
||||||
}
|
}
|
||||||
public XMLComment getCommentAt(int index){
|
public XMLComment getCommentAt(int index){
|
||||||
if(mComments==null || index<0){
|
if(index<0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if(index>=mComments.size()){
|
if(index>=mComments.size()){
|
||||||
@ -213,17 +215,11 @@ public class XMLElement extends XMLNode{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void hideComments(boolean hide){
|
private void hideComments(boolean hide){
|
||||||
if(mComments==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for(XMLComment ce:mComments){
|
for(XMLComment ce:mComments){
|
||||||
ce.setHidden(hide);
|
ce.setHidden(hide);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int getCommentsCount(){
|
public int getCommentsCount(){
|
||||||
if(mComments==null){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return mComments.size();
|
return mComments.size();
|
||||||
}
|
}
|
||||||
public void addComments(Collection<XMLComment> commentElements){
|
public void addComments(Collection<XMLComment> commentElements){
|
||||||
@ -235,11 +231,7 @@ public class XMLElement extends XMLNode{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void clearComments(){
|
public void clearComments(){
|
||||||
if(mComments==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mComments.clear();
|
mComments.clear();
|
||||||
mComments=null;
|
|
||||||
}
|
}
|
||||||
public void addComment(XMLComment commentElement) {
|
public void addComment(XMLComment commentElement) {
|
||||||
addCommentInternal(commentElement, true);
|
addCommentInternal(commentElement, true);
|
||||||
@ -248,9 +240,6 @@ public class XMLElement extends XMLNode{
|
|||||||
if(commentElement==null){
|
if(commentElement==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(mComments==null){
|
|
||||||
mComments=new ArrayList<>();
|
|
||||||
}
|
|
||||||
mComments.add(commentElement);
|
mComments.add(commentElement);
|
||||||
commentElement.setIndent(getIndent());
|
commentElement.setIndent(getIndent());
|
||||||
commentElement.setParent(this);
|
commentElement.setParent(this);
|
||||||
@ -258,8 +247,12 @@ public class XMLElement extends XMLNode{
|
|||||||
super.addChildNodeInternal(commentElement);
|
super.addChildNodeInternal(commentElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void removeChildElements(){
|
@Override
|
||||||
|
void clearChildNodesInternal(){
|
||||||
|
super.clearChildNodesInternal();
|
||||||
mChildElements.clear();
|
mChildElements.clear();
|
||||||
|
mComments.clear();
|
||||||
|
mTexts.clear();
|
||||||
}
|
}
|
||||||
public List<XMLAttribute> listAttributes(){
|
public List<XMLAttribute> listAttributes(){
|
||||||
return mAttributes;
|
return mAttributes;
|
||||||
@ -538,33 +531,41 @@ public class XMLElement extends XMLNode{
|
|||||||
mTag =tag;
|
mTag =tag;
|
||||||
}
|
}
|
||||||
public String getTextContent(){
|
public String getTextContent(){
|
||||||
return getTextContent(true);
|
|
||||||
}
|
|
||||||
public String getTextContent(boolean unEscape){
|
|
||||||
String text=buildTextContent();
|
|
||||||
if(unEscape){
|
|
||||||
text=XMLUtil.unEscapeXmlChars(text);
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
private String buildTextContent(){
|
|
||||||
if(!hasTextContent()){
|
if(!hasTextContent()){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
StringWriter writer=new StringWriter();
|
return buildTextContent();
|
||||||
for(XMLNode child:getChildNodes()){
|
|
||||||
try {
|
|
||||||
child.write(writer, false);
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
}
|
||||||
|
public String buildTextContent(){
|
||||||
|
StringWriter writer=new StringWriter();
|
||||||
|
try {
|
||||||
|
for(XMLNode node:getChildNodes()){
|
||||||
|
node.buildTextContent(writer);
|
||||||
}
|
}
|
||||||
writer.flush();
|
writer.flush();
|
||||||
try {
|
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
return writer.toString();
|
return writer.toString();
|
||||||
}
|
}
|
||||||
|
void buildTextContent(Writer writer) throws IOException {
|
||||||
|
writer.write("<");
|
||||||
|
writer.write(getTagName());
|
||||||
|
appendAttributes(writer, false);
|
||||||
|
if(!hasChildNodes()){
|
||||||
|
writer.write("/>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writer.write('>');
|
||||||
|
for(XMLNode node:getChildNodes()){
|
||||||
|
node.buildTextContent(writer);
|
||||||
|
}
|
||||||
|
if(hasChildNodes()){
|
||||||
|
writer.write("</");
|
||||||
|
writer.write(getTagName());
|
||||||
|
writer.write('>');
|
||||||
|
}
|
||||||
|
}
|
||||||
private void appendTextContent(Writer writer) throws IOException {
|
private void appendTextContent(Writer writer) throws IOException {
|
||||||
for(XMLNode child:getChildNodes()){
|
for(XMLNode child:getChildNodes()){
|
||||||
if(child instanceof XMLElement){
|
if(child instanceof XMLElement){
|
||||||
@ -573,6 +574,9 @@ public class XMLElement extends XMLNode{
|
|||||||
child.write(writer, false);
|
child.write(writer, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public boolean hasChildElements(){
|
||||||
|
return mChildElements.size()>0;
|
||||||
|
}
|
||||||
public boolean hasTextContent() {
|
public boolean hasTextContent() {
|
||||||
return mTexts.size()>0;
|
return mTexts.size()>0;
|
||||||
}
|
}
|
||||||
@ -582,6 +586,17 @@ public class XMLElement extends XMLNode{
|
|||||||
}
|
}
|
||||||
return mTexts.get(0).getText();
|
return mTexts.get(0).getText();
|
||||||
}
|
}
|
||||||
|
public void setSpannableText(String text){
|
||||||
|
clearChildNodes();
|
||||||
|
XMLElement element = parseSpanSafe(text);
|
||||||
|
if(element==null){
|
||||||
|
addText( new XMLText(text));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(XMLNode xmlNode:element.getChildNodes()){
|
||||||
|
super.addChildNode(xmlNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
public void setTextContent(String text){
|
public void setTextContent(String text){
|
||||||
setTextContent(text, true);
|
setTextContent(text, true);
|
||||||
}
|
}
|
||||||
@ -775,4 +790,16 @@ public class XMLElement extends XMLNode{
|
|||||||
return strWriter.toString();
|
return strWriter.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static XMLElement parseSpanSafe(String spanText){
|
||||||
|
if(spanText==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
XMLSpanParser spanParser = new XMLSpanParser();
|
||||||
|
return spanParser.parse(spanText);
|
||||||
|
} catch (XMLException ignored) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,20 @@ public abstract class XMLNode {
|
|||||||
}
|
}
|
||||||
mChildNodes.remove(xmlNode);
|
mChildNodes.remove(xmlNode);
|
||||||
}
|
}
|
||||||
|
public void clearChildNodes(){
|
||||||
|
clearChildNodesInternal();
|
||||||
|
}
|
||||||
|
void clearChildNodesInternal(){
|
||||||
|
mChildNodes.clear();
|
||||||
|
}
|
||||||
public List<XMLNode> getChildNodes() {
|
public List<XMLNode> getChildNodes() {
|
||||||
return mChildNodes;
|
return mChildNodes;
|
||||||
|
}
|
||||||
|
boolean hasChildNodes(){
|
||||||
|
return mChildNodes.size()>0;
|
||||||
|
}
|
||||||
|
void buildTextContent(Writer writer) throws IOException{
|
||||||
|
|
||||||
}
|
}
|
||||||
public boolean write(Writer writer) throws IOException {
|
public boolean write(Writer writer) throws IOException {
|
||||||
return write(writer, false);
|
return write(writer, false);
|
||||||
|
@ -44,6 +44,10 @@ public class XMLText extends XMLNode{
|
|||||||
this.text=XMLUtil.escapeXmlChars(text);
|
this.text=XMLUtil.escapeXmlChars(text);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
void buildTextContent(Writer writer) throws IOException{
|
||||||
|
writer.write(this.text);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
public boolean write(Writer writer, boolean newLineAttributes) throws IOException {
|
public boolean write(Writer writer, boolean newLineAttributes) throws IOException {
|
||||||
if(!XMLUtil.isEmpty(this.text)){
|
if(!XMLUtil.isEmpty(this.text)){
|
||||||
writer.write(this.text);
|
writer.write(this.text);
|
||||||
|
@ -15,7 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.xml;
|
package com.reandroid.xml;
|
||||||
|
|
||||||
public class XmlHeaderElement extends XMLElement {
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
public class XmlHeaderElement extends XMLElement {
|
||||||
private static final String ATTR_VERSION="version";
|
private static final String ATTR_VERSION="version";
|
||||||
private static final String ATTR_ENCODING="encoding";
|
private static final String ATTR_ENCODING="encoding";
|
||||||
private static final String ATTR_STANDALONE="standalone";
|
private static final String ATTR_STANDALONE="standalone";
|
||||||
@ -100,4 +103,8 @@ public class XmlHeaderElement extends XMLElement {
|
|||||||
int getIndent(){
|
int getIndent(){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
void buildTextContent(Writer writer) throws IOException {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user