From 193a9b66ee574ebbc1757a78fed3b4679c8fecca Mon Sep 17 00:00:00 2001 From: REAndroid Date: Sat, 6 May 2023 18:25:44 +0200 Subject: [PATCH] fix parse styled strings --- .../xmlencoder/XMLValuesEncoderString.java | 47 ++++++---- .../reandroid/arsc/model/StyleSpanInfo.java | 5 +- .../java/com/reandroid/xml/XMLSpannable.java | 93 ++++++++++++++----- 3 files changed, 106 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoderString.java b/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoderString.java index 5520d92..3d8a003 100644 --- a/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoderString.java +++ b/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoderString.java @@ -1,28 +1,39 @@ - /* - * 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. - */ +/* + * 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.apk.xmlencoder; import com.reandroid.arsc.decoder.ValueDecoder; import com.reandroid.arsc.value.Entry; +import com.reandroid.xml.XMLElement; +import com.reandroid.xml.XMLSpannable; - class XMLValuesEncoderString extends XMLValuesEncoder{ +class XMLValuesEncoderString extends XMLValuesEncoder{ XMLValuesEncoderString(EncodeMaterials materials) { super(materials); } + + @Override + void encodeValue(Entry entry, XMLElement element){ + if(!element.hasChildElements()){ + super.encodeValue(entry, element); + return; + } + encodeStyledString(entry, element); + } @Override void encodeStringValue(Entry entry, String value){ entry.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value)); @@ -35,4 +46,8 @@ import com.reandroid.arsc.value.Entry; void encodeBooleanValue(Entry entry, String value){ entry.setValueAsString(value); } + private void encodeStyledString(Entry entry, XMLElement element){ + XMLSpannable xmlSpannable = new XMLSpannable(element); + entry.setValueAsString(xmlSpannable.getXml()); + } } diff --git a/src/main/java/com/reandroid/arsc/model/StyleSpanInfo.java b/src/main/java/com/reandroid/arsc/model/StyleSpanInfo.java index 3be2d09..89b61e4 100755 --- a/src/main/java/com/reandroid/arsc/model/StyleSpanInfo.java +++ b/src/main/java/com/reandroid/arsc/model/StyleSpanInfo.java @@ -1,4 +1,4 @@ - /* +/* * Copyright (C) 2022 github.com/REAndroid * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -85,6 +85,9 @@ public class StyleSpanInfo implements JSONConvert { public String getEndTag(){ int i= mTag.indexOf(';'); + if(i < 0){ + i = mTag.indexOf(' '); + } StringBuilder builder=new StringBuilder(); builder.append('<'); builder.append('/'); diff --git a/src/main/java/com/reandroid/xml/XMLSpannable.java b/src/main/java/com/reandroid/xml/XMLSpannable.java index ae4cc6f..859e91b 100644 --- a/src/main/java/com/reandroid/xml/XMLSpannable.java +++ b/src/main/java/com/reandroid/xml/XMLSpannable.java @@ -1,29 +1,29 @@ - /* - * 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. - */ +/* + * 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.xml; import com.reandroid.xml.parser.XMLSpanParser; import java.util.*; - public class XMLSpannable implements Comparable{ +public class XMLSpannable implements Comparable{ private XMLElement mElement; private String mText; private List mSpanInfoList; - private XMLSpannable(XMLElement element){ + public XMLSpannable(XMLElement element){ this.mElement=element; } public boolean isValid(){ @@ -38,6 +38,47 @@ import java.util.*; } return true; } + public String getXml(){ + StringBuilder builder = new StringBuilder(); + for(XMLNode xmlNode: mElement.getChildNodes()){ + if(xmlNode instanceof XMLElement){ + appendXml(builder, (XMLElement) xmlNode); + }else if(xmlNode instanceof XMLText){ + appendXml(builder, (XMLText) xmlNode); + } + } + return builder.toString(); + } + private void appendXml(StringBuilder builder, XMLElement element){ + builder.append('<'); + builder.append(element.getTagName()); + appendXmlAttributes(builder, element); + builder.append('>'); + for(XMLNode xmlNode: element.getChildNodes()){ + if(xmlNode instanceof XMLElement){ + appendXml(builder, (XMLElement) xmlNode); + }else if(xmlNode instanceof XMLText){ + appendXml(builder, (XMLText) xmlNode); + } + } + builder.append('<'); + builder.append('/'); + builder.append(element.getTagName()); + builder.append('>'); + } + private void appendXmlAttributes(StringBuilder builder, XMLElement element){ + for(XMLAttribute xmlAttribute : element.listAttributes()){ + builder.append(' '); + builder.append(xmlAttribute.getName()); + builder.append('='); + builder.append('"'); + builder.append(xmlAttribute.getValue()); + builder.append('"'); + } + } + private void appendXml(StringBuilder builder, XMLText xmlText){ + builder.append(xmlText.getText(true)); + } public String getText(){ if(mText==null){ buildSpanInfo(); @@ -58,11 +99,15 @@ import java.util.*; mElement=null; } private void buildSpanInfo(XMLElement element, StringBuilder builder){ - XMLSpanInfo info=null; + XMLSpanInfo info = null; for(XMLNode node:element.listSpannable()){ - if(info!=null){ - info.end=builder.length(); - info=null; + if(info != null){ + int pos = builder.length(); + if(pos > 0){ + pos = pos - 1; + } + info.end = pos; + info = null; } if(node instanceof XMLText){ builder.append(((XMLText)node).getText()); @@ -76,7 +121,11 @@ import java.util.*; buildSpanInfo(child, builder); } if(info!=null){ - info.end=builder.length(); + int pos = builder.length(); + if(pos > 0){ + pos = pos - 1; + } + info.end = pos; } } @Override