简体   繁体   English

如何在Gradle Kotlin中合并两个.xml文件?

[英]How to merge two .xml files in Gradle Kotlin?

I am new to Kotlin, and I am attempting to convert a simple xml file merge task written in Groovy into Kotlin. 我是Kotlin的新手,我正在尝试将用Groovy编写的简单xml文件合并任务转换为Kotlin。

In Gradle Groovy DSL, I can merge two xml files as shown in the code below, how can I accomplish the same in Kotlin? 在Gradle Groovy DSL中,我可以合并两个xml文件,如下面的代码所示,我如何在Kotlin中完成相同的操作?

The mergeXml below merges the both inventory.xml and order.xml file into inventory.xml file. 下面的mergeXml将inventory.xml和order.xml文件合并到inventory.xml文件中。

I have 2 .xml files with following contents: 我有2个.xml文件,内容如下:

inventory.xml inventory.xml

<?xml version="1.0" encoding="UTF-8"?>
<cars>
    <car>GM</car>
    <car>Ford</car>
</cars>

order.xml order.xml

<?xml version="1.0" encoding="UTF-8"?>
<cars>
    <car>Acura</car>
    <car>Honda</car>
</cars>
plugins {
    id 'org.springframework.boot' version '2.1.4.RELEASE'
    id 'java'
}

apply plugin: 'io.spring.dependency-management'

sourceCompatibility = '1.8'

ext.libraries = [
    frameworkLibs: [
        'org.springframework.boot:spring-boot-starter-data-redis',
        'org.springframework.boot:spring-boot-starter-web',
        'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.0.1',
        'org.springframework.kafka:spring-kafka'
    ],
    testLibs: [
        'org.springframework.boot:spring-boot-starter-test',
        'org.springframework.kafka:spring-kafka-test'
    ],
    sqlLibs: [
        'org.postgresql:postgresql'
    ]
]

allprojects {
    group = 'com.example'
    version = '0.0.1-SNAPSHOT'

    repositories {
        mavenCentral()
    }

    dependencies {
        implementation libraries.frameworkLibs
        runtimeOnly libraries.sqlLibs
        testImplementation libraries.testLibs
    }
}

// How to convert following code into Kotlin?
task mergeXml {
    final inventory = new File("$rootDir/src/main/resources/inventory.xml")
    final inventoryContent = inventory.getText()
    final order = new File("$rootDir/src/main/resources/order.xml")
    final orderContent = order.getText()

    doLast {
        def rootNode = new XmlParser().parseText(inventoryContent)
        def printWriter = new PrintWriter(inventory)
        def xmlNodePrinter = new XmlNodePrinter(printWriter)

        new XmlParser().parseText(orderContent).children().each { rootNode.append(it) }
        printWriter.print(inventoryContent.split("(?=<cars)")[0])
        xmlNodePrinter.print(rootNode)
    }
}

I am looking for following result overwritten in inventory.xml file using Kotlin. 我正在寻找使用Kotlin在inventory.xml文件中覆盖的以下结果。

<?xml version="1.0" encoding="UTF-8"?>
<cars>
  <car>
    GM
  </car>
  <car>
    Ford
  </car>
  <car>
    Acura
  </car>
  <car>
    Honda
  </car>
</cars>

you need to reimplement your merge logic in kotlin: 你需要在kotlin中重新实现你的合并逻辑:

  • use val instead of def ( Variables ) 使用val而不是def变量
  • you don't need new to invoke the constructor of a class ( creating classes ) 你不需要new来调用类的构造函数( 创建类
  • use the appropiate Kotlin functions to replace groovy code (eg readText() instead of getText() to read a File to a String. 使用适当的Kotlin函数来替换groovy代码(例如readText()而不是getText()来将File读取到String。
  • ... ...

It should look something like: 它应该看起来像:

fun mergeXmlFiles(file1: File, file2: File) {
   val text1 = file.readText()
   ...
   val rootNode = XmlParser().parseText(inventoryContent)
   val printWriter = PrintWriter(inventory)
   val xmlNodePrinter = XmlNodePrinter(printWriter)
   ... 
}

then you can use your custom function from your build script: 然后您可以使用构建脚本中的自定义函数:

tasks {
   val mergeXml by creating {
     doLast {
       mergeXmlFiles(File(...), File(...))
     }
   }
}

I figured it out. 我想到了。 It is not as slick or intuitive as it is in Groovy (required a lot of work). 它不像Groovy那样灵活或直观(需要大量工作)。 Please advise if there are better approaches. 请告知是否有更好的方法。

  1. In the project root directory, create file /buildSrc/src/main/kotlin/XmlUtility.kt with following content. 在项目根目录中,使用以下内容创建文件/buildSrc/src/main/kotlin/XmlUtility.kt。
/*
 * This file includes utilities for processing XML in Kotlin DSL
 *
 */

import javax.xml.parsers.DocumentBuilderFactory;
import org.xml.sax.InputSource
import java.io.StringReader
import java.io.File

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

object XmlUtility {


    fun mergeSaveXml(orgXml: String, newXml: String, filePath: String) {

        val finalDocument = mergeXml(orgXml, newXml)

        val transformerFactory = TransformerFactory.newInstance()
        val transformer = transformerFactory.newTransformer()
        val domSource = DOMSource(finalDocument)
        val streamResult = StreamResult(File(filePath))
        transformer.transform(domSource, streamResult)
    }

    fun mergeXml(originalContent:String, newContent: String): Document  {
        val dbFactory = DocumentBuilderFactory.newInstance()
        val dBuilder  = dbFactory.newDocumentBuilder()

        val xmlOrgInput = InputSource(StringReader(originalContent))
        val xmlOrgDoc = dBuilder.parse(xmlOrgInput)
        val xmlOrgEle = xmlOrgDoc.getDocumentElement()

        val xmlNewInput = InputSource(StringReader(newContent))
        val xmlNewgDoc = dBuilder.parse(xmlNewInput)
        val xmlNewEle = xmlNewgDoc.getDocumentElement()
        val xmlNewNde = xmlNewEle.getChildNodes()

        for (i in 0 until xmlNewNde.length) {
            val xmlNode = xmlNewNde.item(i)
            if (xmlNode.nodeType == Node.ELEMENT_NODE) {
                val xmlImportedNode = xmlOrgDoc.importNode(xmlNode, true)
                xmlOrgEle.appendChild(xmlImportedNode)
            }
        }       
        return xmlOrgDoc
    }
}
  1. Then call it from Gradle task 然后从Gradle任务中调用它
task mergeXml {
    final inventory = new File("$rootDir/src/main/resources/inventory.xml")
    final inventoryContent = inventory.getText()
    final order = new File("$rootDir/src/main/resources/order.xml")
    final orderContent = order.getText()

    doLast {
         mergeSaveXml(inventoryContent, orderContent, "$rootDir/src/main/resources/inventory.xml")
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM