Как объединить два файла .xml в Gradle Kotlin? - PullRequest
0 голосов
/ 21 мая 2019

Я новичок в Kotlin, и я пытаюсь преобразовать простую задачу слияния XML-файлов, написанную в Groovy, в Kotlin.

В Gradle Groovy DSL я могу объединить два XML-файла, как показано в приведенном ниже коде, как я могу сделать то же самое в Kotlin?

Приведенный ниже mergeXml объединяет оба файла инвентаризации.xml и order.xml в файл inventory.xml.

У меня есть 2 XML-файла со следующим содержимым:

Inventory.xml

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

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)
    }
}

Я ищу следующий результат, перезаписанный в файле inventory.xml с помощью Kotlin.

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

Ответы [ 2 ]

0 голосов
/ 22 мая 2019

Я понял это. Это не так гладко и интуитивно понятно, как в Groovy (требуется много работы). Пожалуйста, сообщите, если есть лучшие подходы.

  1. В корневом каталоге проекта создайте файл /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. Затем вызовите его из задачи 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")
    }
}
0 голосов
/ 21 мая 2019

вам нужно переопределить логику слияния в kotlin:

  • использовать val вместо def ( Variables )
  • вам не нужно new для вызова конструктора класса ( создание классов )
  • использование подходящих функций Kotlin для замены Groovy-кода (например, readText () вместо getText () для чтения файла в строку.
  • ...

Это должно выглядеть как-тонапример:

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

, затем вы можете использовать пользовательскую функцию из скрипта сборки:

tasks {
   val mergeXml by creating {
     doLast {
       mergeXmlFiles(File(...), File(...))
     }
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...