使用IntelliJ IDEA 2023.2.4 (Community Edition)创建kotlin+gradle项目,主要解决aosp项目中strings相同name但是有不同product时在android studio编译报错的问题
如下:

    <string name="sdcard_unmount" product="nosdcard" msgid="1816306320988638382">"Ontheg USB-berging"</string>
    <string name="sdcard_unmount" product="default" msgid="8078570285871053815">"Ontkoppel SD-kaart"</string>
    <string name="sdcard_format" product="nosdcard" msgid="3248760426252305366">"Vee USB-berging uit"</string>
    <string name="sdcard_format" product="default" msgid="3676635435136326182">"Vee SD-kaart uit"</string>

gradle配置依赖如下:
build.gradle.kt:

    implementation("dom4j:dom4j:1.6.1")
    implementation("jaxen:jaxen:1.2.0")

product筛选主要处理逻辑如下:
Main.kt

import org.dom4j.Document
import org.dom4j.Element
import org.dom4j.io.SAXReader
import org.dom4j.io.XMLWriter
import java.io.File
import java.io.FileWriter
import java.lang.StringBuilder

/**
 * 定义xml中string数据存储类
 */
data class StringDataItem(val name: String, val product: String?, val content: String)

/**
 * 根据name和product删除节点
 */
fun deleteElement(doc: Document, name: String, product: String) {
    val xpath = "//string[@name='$name' and @product='$product']"
    val node = doc.selectSingleNode(xpath) ?: return
    node.parent.remove(node)
}

/**
 * 打印所有可用product
 */
fun printAllProduct(doc: Document) {
    val list = doc.rootElement.elements("string")
    val productNameList = mutableListOf<String>()
    for (stringItem in list) {
        stringItem as Element
        val productName = stringItem.attributeValue("product")
        if (productNameList.contains(productName)) {
            continue
        }
        productName?.let {
            productNameList.add(it)
        }
    }
    println("当前xml文档所含有的product类型: $productNameList")
}

/**
 * 解析xml文档
 */
fun parseXml(xmlPath: String, product: String = "default") {
    println("------------aaa.xml parse start------------")
    println("当前处理的xml文件路径:$xmlPath")
    val file = File(xmlPath)
    val saxReader = SAXReader()
    val document = saxReader.read(file)
    printAllProduct(document)
    val list = mutableListOf<StringDataItem>()
    //key = stringName
    val map1 = mutableMapOf<String, MutableList<StringDataItem>>()
    for (element in document.rootElement.elements("string")) {
        element as Element;
        val content = element.text
        val avName = element.attributeValue("name")
        //如果当前节点product属性为null,则直接处理下一节点
        val avProduct = element.attributeValue("product") ?: continue
        list.add(StringDataItem(avName, avProduct, content))
        if (map1.containsKey(avName)) {
            val itemList = map1[avName]
            itemList?.add(StringDataItem(avName, avProduct, content))
        } else {
            val iteList = mutableListOf<StringDataItem>()
            iteList.add(StringDataItem(avName, avProduct, content))
            map1[avName] = iteList
        }
    }
    for (name in map1.keys) {
        val list = map1[name]
        list as MutableList<StringDataItem>
        val builder = StringBuilder()
        for (item in list) {
            builder.append(item.product)
                .append(",")
        }
    }
    //删除非指定product类型的string节点
    for (stringName in map1.keys) {
        //相同name的string资源
        val itemList = map1[stringName]
        itemList as MutableList<StringDataItem>

        //有type选type,没type选default,
        //key = productName
        val typeIndexList = mutableMapOf<String, StringDataItem>()
        itemList.forEach {
            val productName = it.product ?: return
            typeIndexList[productName] = it
        }
        if (typeIndexList.containsKey(product)) {
            typeIndexList.remove(product)
            for (productName in typeIndexList.keys) {
                if (product != productName) {
                    typeIndexList[productName]?.let {
                        deleteElement(document, it.name, it.product!!)
                    }
                }
            }
        } else if (typeIndexList.containsKey("default")) {
            for (productName in typeIndexList.keys) {
                if ("default" != productName) {
                    typeIndexList[productName]?.let {
                        deleteElement(document, it.name, it.product!!)
                    }
                }
            }
        } else {
            throw Exception("解析xml出错了:$stringName")
        }
    }
    val writer = XMLWriter(FileWriter(File(xmlPath)))
    writer.write(document)
    writer.close()
}

fun main(args: Array<String>) {
    println("----------------------------------------")
    println("AOSP项目strings.xml字符串product去重工具")
    println("----------------------------------------")

    println("请输入res路径")
    val resDirPath = readlnOrNull()
    if (resDirPath == null || resDirPath == "") {
        println("没有输入res路径,程序退出")
        return
    }
    println("请输入要保留的product类型,可选项为[nosdcard, default, tablet, device, emulator, phone]")
    var selectProduct = readlnOrNull()
    if (selectProduct == null || selectProduct == "") {
        println("没有输入product类型,程序退出")
        return
    }

    File(resDirPath).listFiles()?.forEach {
        if (it.name.startsWith("values")) {
            it.listFiles()?.forEach { childFile ->
                if ("strings.xml" == childFile.name) {
                    parseXml(childFile.absolutePath, selectProduct)
                }
            }
        }
    }
}

下载链接:
https://download.csdn.net/download/qq_15050521/88541575

如果你觉得这篇文章帮助到了你,欢迎打赏
在这里插入图片描述

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐