diff --git a/CHANGELOG.md b/CHANGELOG.md index 19cb94a..be87e8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Change Log ========== +Version 2.3.0 +--- + +* Keeping xml tags from xml string body. + Version 2.2.2 --- diff --git a/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/AndroidXmlResDocument.kt b/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/AndroidXmlResDocument.kt index 9a7b8d4..0630c49 100644 --- a/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/AndroidXmlResDocument.kt +++ b/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/AndroidXmlResDocument.kt @@ -13,6 +13,9 @@ import javax.xml.transform.OutputKeys import javax.xml.transform.TransformerFactory import javax.xml.transform.dom.DOMSource import javax.xml.transform.stream.StreamResult +import javax.xml.xpath.XPath +import javax.xml.xpath.XPathConstants +import javax.xml.xpath.XPathFactory class AndroidXmlResDocument(private val document: Document) { @@ -39,6 +42,7 @@ class AndroidXmlResDocument(private val document: Document) { } private val resources: Element by lazy { getOrCreateResources() } + private val xPath: XPath by lazy { XPathFactory.newInstance().newXPath() } fun saveToFile(file: File, indentSpaces: Int = 4) { val transformerFactory = TransformerFactory.newInstance() @@ -66,8 +70,8 @@ class AndroidXmlResDocument(private val document: Document) { } } - fun getElementsByTagName(name: String): NodeList { - return resources.getElementsByTagName(name) + fun getElementsByXPath(xpath: String): NodeList { + return xPath.compile(xpath).evaluate(document, XPathConstants.NODESET) as NodeList } private fun getOrCreateResources(): Element { diff --git a/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlFileFinder.kt b/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlFileFinder.kt deleted file mode 100644 index 6a2231b..0000000 --- a/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlFileFinder.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.likethesalad.tools.resource.collector.android.data.xml - -import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDir -import java.io.File - -object XmlFileFinder { - - private val XML_FORMAT = Regex(".+\\.[xX][mM][lL]\$") - - fun findXmlFiles(valueDir: ValueDir): List { - return valueDir.dir.listFiles { _, name -> - isXmlFile(name) - }?.toList() ?: emptyList() - } - - private fun isXmlFile(name: String): Boolean { - return XML_FORMAT.matches(name) - } -} \ No newline at end of file diff --git a/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlUtils.kt b/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlUtils.kt new file mode 100644 index 0000000..e52b8ba --- /dev/null +++ b/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlUtils.kt @@ -0,0 +1,44 @@ +package com.likethesalad.tools.resource.collector.android.data.xml + +import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDir +import org.w3c.dom.Node +import java.io.File +import java.io.StringWriter +import javax.xml.transform.OutputKeys +import javax.xml.transform.TransformerException +import javax.xml.transform.TransformerFactory +import javax.xml.transform.dom.DOMSource +import javax.xml.transform.stream.StreamResult + +object XmlUtils { + + private val XML_FORMAT = Regex(".+\\.[xX][mM][lL]\$") + private val OUTER_XML_TAGS_PATTERN = Regex("^<[^>]*>|<[^>]*>\$") + private val contentExtractor by lazy { + val transformer = TransformerFactory.newInstance().newTransformer() + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes") + transformer + } + + fun findXmlFiles(valueDir: ValueDir): List { + return valueDir.dir.listFiles { _, name -> + isXmlFile(name) + }?.toList() ?: emptyList() + } + + private fun isXmlFile(name: String): Boolean { + return XML_FORMAT.matches(name) + } + + fun getContents(node: Node): String { + val outText = StringWriter() + val streamResult = StreamResult(outText) + return try { + contentExtractor.transform(DOMSource(node), streamResult) + val text = outText.toString() + return OUTER_XML_TAGS_PATTERN.replace(text, "") + } catch (e: TransformerException) { + node.textContent + } + } +} \ No newline at end of file diff --git a/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/source/providers/ResDirResourceSourceProvider.kt b/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/source/providers/ResDirResourceSourceProvider.kt index b676799..ac78fd2 100644 --- a/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/source/providers/ResDirResourceSourceProvider.kt +++ b/android-resource-collector/src/main/java/com/likethesalad/tools/resource/collector/android/source/providers/ResDirResourceSourceProvider.kt @@ -4,7 +4,7 @@ import com.likethesalad.tools.resource.api.android.impl.AndroidResourceScope import com.likethesalad.tools.resource.collector.android.data.resdir.ResDir import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDir import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDirFinder -import com.likethesalad.tools.resource.collector.android.data.xml.XmlFileFinder +import com.likethesalad.tools.resource.collector.android.data.xml.XmlUtils import com.likethesalad.tools.resource.collector.android.source.AndroidXmlResourceSource import com.likethesalad.tools.resource.collector.source.ResourceSource import com.likethesalad.tools.resource.collector.source.ResourceSourceProvider @@ -25,7 +25,7 @@ class ResDirResourceSourceProvider(private val resDir: ResDir) : ResourceSourceP private fun extractSourcesFromValueDir(valueDir: ValueDir): Collection { val sources = mutableListOf() - val xmlFiles = XmlFileFinder.findXmlFiles(valueDir) + val xmlFiles = XmlUtils.findXmlFiles(valueDir) val scope = AndroidResourceScope(valueDir.resDir.variant, valueDir.language) for (file in xmlFiles) { diff --git a/android-resource-collector/src/test/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlFileFinderTest.kt b/android-resource-collector/src/test/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlUtilsTest.kt similarity index 70% rename from android-resource-collector/src/test/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlFileFinderTest.kt rename to android-resource-collector/src/test/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlUtilsTest.kt index ed19a53..4d1ddd4 100644 --- a/android-resource-collector/src/test/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlFileFinderTest.kt +++ b/android-resource-collector/src/test/java/com/likethesalad/tools/resource/collector/android/data/xml/XmlUtilsTest.kt @@ -7,9 +7,12 @@ import com.likethesalad.tools.resource.collector.android.data.valuedir.ValueDir import com.likethesalad.tools.testing.DummyResourcesFinder.getResourceFile import io.mockk.mockk import org.junit.Test +import java.io.ByteArrayInputStream import java.io.File +import javax.xml.parsers.DocumentBuilderFactory -class XmlFileFinderTest { + +class XmlUtilsTest { @Test fun `Find xml files`() { @@ -35,10 +38,21 @@ class XmlFileFinderTest { Truth.assertThat(files).isEmpty() } + @Test + fun `Extract text from node`() { + val node = DocumentBuilderFactory + .newInstance() + .newDocumentBuilder() + .parse(ByteArrayInputStream("value something bold".toByteArray())) + .documentElement + + Truth.assertThat(XmlUtils.getContents(node)).isEqualTo("value something bold") + } + private fun findXmlFilesFromFolder(folder: File): List { val resDir = mockk() val valuesDir = ValueDir(resDir, folder, Language.Default) - return XmlFileFinder.findXmlFiles(valuesDir) + return XmlUtils.findXmlFiles(valuesDir) } } \ No newline at end of file diff --git a/android-resource-serializer/src/main/java/com/likethesalad/resource/serializer/android/AndroidResourceSerializer.kt b/android-resource-serializer/src/main/java/com/likethesalad/resource/serializer/android/AndroidResourceSerializer.kt index 60dcfc5..b693c84 100644 --- a/android-resource-serializer/src/main/java/com/likethesalad/resource/serializer/android/AndroidResourceSerializer.kt +++ b/android-resource-serializer/src/main/java/com/likethesalad/resource/serializer/android/AndroidResourceSerializer.kt @@ -1,6 +1,6 @@ package com.likethesalad.resource.serializer.android -import com.google.gson.Gson +import com.google.gson.GsonBuilder import com.likethesalad.resource.serializer.android.internal.AndroidResourceJsonCollection import com.likethesalad.resource.serializer.android.internal.AndroidResourceJsonStructure import com.likethesalad.resource.serializer.android.internal.AndroidResourceMapper @@ -12,7 +12,11 @@ import com.likethesalad.tools.resource.serializer.ResourceSerializer class AndroidResourceSerializer : ResourceSerializer { - private val gson by lazy { Gson() } + private val gson by lazy { + GsonBuilder() + .disableHtmlEscaping() + .create() + } override fun serialize(resource: Resource): String { val jsonStructure = AndroidResourceMapper.mapToJson(resource as AndroidResource) diff --git a/gradle.properties b/gradle.properties index 1570531..8e6dd17 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ kotlin.code.style=official kotlin.version=1.9.22 group=com.likethesalad.tools.resources -version=2.2.2 +version=2.3.0 diff --git a/string-android-resource-locator/src/main/java/com/likethesalad/android/string/resources/locator/extractor/StringXmlResourceExtractor.kt b/string-android-resource-locator/src/main/java/com/likethesalad/android/string/resources/locator/extractor/StringXmlResourceExtractor.kt index ef8eb64..287b87e 100644 --- a/string-android-resource-locator/src/main/java/com/likethesalad/android/string/resources/locator/extractor/StringXmlResourceExtractor.kt +++ b/string-android-resource-locator/src/main/java/com/likethesalad/android/string/resources/locator/extractor/StringXmlResourceExtractor.kt @@ -7,6 +7,7 @@ import com.likethesalad.tools.resource.api.android.impl.AndroidResourceScope import com.likethesalad.tools.resource.api.android.modules.string.StringAndroidResource import com.likethesalad.tools.resource.api.attributes.AttributeKey import com.likethesalad.tools.resource.collector.android.data.AndroidXmlResDocument +import com.likethesalad.tools.resource.collector.android.data.xml.XmlUtils import com.likethesalad.tools.resource.collector.android.extractor.XmlResourceExtractor import org.w3c.dom.Node import org.w3c.dom.NodeList @@ -14,7 +15,7 @@ import org.w3c.dom.NodeList class StringXmlResourceExtractor : XmlResourceExtractor() { companion object { - private const val XML_STRING_TAG = "string" + private const val STRING_RESOURCE_PATH = "/resources/string" } override fun getResourcesFromAndroidDocument( @@ -40,7 +41,7 @@ class StringXmlResourceExtractor : XmlResourceExtractor() private fun parseNodeToStringAndroidResource(node: Node, scope: Resource.Scope): StringAndroidResource { val attributesMap = mutableMapOf() - val value = trimQuotes(node.textContent) + val value = trimQuotes(getNodeText(node)) val attributesNodes = node.attributes for (index in 0 until attributesNodes.length) { val attr = attributesNodes.item(index) @@ -55,11 +56,15 @@ class StringXmlResourceExtractor : XmlResourceExtractor() return StringAndroidResource(attributesMap, value, scope as AndroidResourceScope) } + private fun getNodeText(node: Node): String { + return XmlUtils.getContents(node) + } + private fun trimQuotes(text: String): String { return text.replace(Regex("(?1 true Just one more string + Some string with tags \ No newline at end of file diff --git a/string-android-resource-locator/src/test/java/com/likethesalad/android/string/resources/locator/extractor/StringXmlResourceExtractorTest.kt b/string-android-resource-locator/src/test/java/com/likethesalad/android/string/resources/locator/extractor/StringXmlResourceExtractorTest.kt index ca5a92b..91a3617 100644 --- a/string-android-resource-locator/src/test/java/com/likethesalad/android/string/resources/locator/extractor/StringXmlResourceExtractorTest.kt +++ b/string-android-resource-locator/src/test/java/com/likethesalad/android/string/resources/locator/extractor/StringXmlResourceExtractorTest.kt @@ -27,6 +27,7 @@ class StringXmlResourceExtractorTest { StringAndroidResource("string_4", "Some partially quoted string", scope), StringAndroidResource("string_5", "Some partially quoted escaped \\\"string\\\"", scope), StringAndroidResource("string_7", "Just one more string", scope), + StringAndroidResource("string_8", "Some string with tags", scope), StringAndroidResource("string_3", "Some quoted string", scope), StringAndroidResource( mapOf(plain("name") to "string_2", plain("translatable") to "false"),