groovy 如果节点不存在,是否将其添加到XML?

hec6srdp  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(142)

我有以下问题。我需要添加一个节点,如果它不可用。例如
输入:

<DataTable>
    <DataRow>
        <Field1>1</Field1>
    </DataRow>
    <DataRow>
        <Field1>1</Field1>
        <Field2>1</Field2>
    </DataRow>
    <DataRow>
        <Field1>1</Field1>
        <Field2>1</Field2>
        <Field3>1</Field3>
    </DataRow>
</DataTable>

预期输出:

<DataTable>
    <DataRow>
        <Field1>1</Field1>
        <Field2/>
        <Field3/>
    </DataRow>
    <DataRow>
        <Field1>1</Field1>
        <Field2>1</Field2>
        <Field3/>
    </DataRow>
    <DataRow>
        <Field1>1</Field1>
        <Field2>1</Field2>
        <Field3>1</Field3>
    </DataRow>
</DataTable>

因此,如果一行中的三个节点不可用,则应将它们添加到结果XML中。
这是我试过的代码,它只适用于平面xml。

import com.sap.gateway.ip.core.customdev.util.Message
import groovy.xml.XmlUtil

Message processData(Message message) {
    def fields = ['Field1', 'Field2', 'Field3']
    def payload = new XmlParser().parse(message.getBody(Reader))
    (fields - (payload.children() as List<Node>)*.name()).each { payload.appendNode(it) }
    message.setBody(XmlUtil.serialize(payload))
    return message
}

我想将标记添加到输出文件。谢谢

nfs0ujit

nfs0ujit1#

因此,对于转换,我们可以编写一个函数,该函数接受一个字符串(输入xml)和一系列必需字段,并返回新的xml。

import groovy.xml.XmlParser
import groovy.xml.XmlNodePrinter

String extendFields(String xmlInput, List<String> fields) {
    def xml = new XmlParser().parseText(xmlInput)
    xml.findAll { it.name() == 'DataRow' }.each { row ->
        fields.each { field ->
            if (!row."$field") {
                row.appendNode(field)
            }
        }
    }
    new StringWriter().with { out ->
        new XmlNodePrinter(new PrintWriter(out)).with { writer ->
            writer.preserveWhitespace = true
            writer.print(xml)
        }
        out.toString()
    }
}

使用输入XML调用此函数:

def input = '''<DataTable>
    <DataRow>
        <Field1>1</Field1>
    </DataRow>
    <DataRow>
        <Field1>1</Field1>
        <Field2>1</Field2>
    </DataRow>
    <DataRow>
        <Field1>1</Field1>
        <Field2>1</Field2>
        <Field3>1</Field3>
    </DataRow>
</DataTable>'''

println extendFields(input, ['Field1', 'Field2', 'Field3'])

印刷品

<DataTable>
  <DataRow>
    <Field1>1</Field1>
    <Field2/>
    <Field3/>
  </DataRow>
  <DataRow>
    <Field1>1</Field1>
    <Field2>1</Field2>
    <Field3/>
  </DataRow>
  <DataRow>
    <Field1>1</Field1>
    <Field2>1</Field2>
    <Field3>1</Field3>
  </DataRow>
</DataTable>

因此,您可以更改问题中的方法,以调用此新方法:

Message processData(Message message) {
    def fields = ['Field1', 'Field2', 'Field3']
    def payload = extendFields(message.getBody(Reader), fields)
    message.setBody(payload)
    return message
}

把它放到一个单独的方法中还有一个好处,那就是它更容易测试😀

编辑

如果您想按照您提供的字段顺序对节点进行排序,可以在children上添加一个sort,如下所示:

String extendFields(String xmlInput, List<String> fields) {
    def xml = new XmlParser().parseText(xmlInput)
    xml.findAll { it.name() == 'DataRow' }.each { row ->
        fields.each { field ->
            if (!row."$field") {
                row.appendNode(field)
            }
        }
        row.children().sort { fields.indexOf(it.name()) }
    }
    new StringWriter().with { out ->
        new XmlNodePrinter(new PrintWriter(out)).with { writer ->
            writer.preserveWhitespace = true
            writer.print(xml)
        }
        out.toString()
    }
}

然后按照我们想要的顺序调用这个函数:

println extendFields(input, ['Field3', 'Field1', 'Field2'])

印刷品:

<DataTable>
  <DataRow>
    <Field3/>
    <Field1>1</Field1>
    <Field2/>
  </DataRow>
  <DataRow>
    <Field3/>
    <Field1>1</Field1>
    <Field2>1</Field2>
  </DataRow>
  <DataRow>
    <Field3>1</Field3>
    <Field1>1</Field1>
    <Field2>1</Field2>
  </DataRow>
</DataTable>

相关问题