简体   繁体   English

XML如果不存在,添加节点?

[英]Add node to the XML if does not exist?

i have following problem.我有以下问题。 I need to add a Node, if its not available.如果节点不可用,我需要添加一个节点。 For example例如

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>

Expected output:预计 output:

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

So if the three nodes in a row are not available, than they should be added to the result XML.因此,如果一行中的三个节点不可用,则应将它们添加到结果 XML 中。

This the code I tried, it works only with a flat 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
}

I want to add Tag to the output file.我想将 Tag 添加到 output 文件中。 Thank you谢谢

So, for the conversion we can write a function that takes a string (the input xml) and a list of required fields, and returns the new xml因此,对于转换,我们可以编写一个 function,它接受一个字符串(输入 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()
    }
}

Calling this with your input XML:使用您的输入 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'])

prints印刷

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

So then, you can change your method in the question to call this new method:那么,您可以更改问题中的方法以调用此新方法:

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

Pulling this out into a separate method also has the advantage of making it more easily testable将其提取到单独的方法中还具有使其更易于测试的优点

Edit编辑

If you want to sort the nodes in the order of the fields you provide, you can add a sort on the children like so:如果你想按照你提供的字段的顺序对节点进行排序,你可以像这样在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()
    }
}

Then calling this with the fields in the order we want:然后按照我们想要的顺序使用字段调用它:

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

Prints:印刷:

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

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

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