如何根据字段名groovy对XML记录进行分组

时间:2019-02-26 18:30:50

标签: xml groovy grouping

我有一个要求,我需要读取具有多种记录类型(按字段区分)的输入XML,然后根据相似的值将这些记录分为不同的记录类型。

输入XML是:

<?xml version='1.0' encoding='UTF-8'?>
<records>
  <record>
    <empID>80000000</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>A</FieldName>
    <NewIDorValue>C HACIENDA DEL PEÑASCO 1271</NewIDorValue>
  </record>
  <record>
    <empID>80000000</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>A</FieldName>
    <NewIDorValue>400</NewIDorValue>
  </record>
  <record>
    <empID>80000000</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>B</FieldName>
    <NewIDorValue>PLAZAS DEL SOL1</NewIDorValue>
  </record>
  <record>
    <empID>80000001</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>B</FieldName>
    <NewIDorValue>Querétaro</NewIDorValue>
  </record>
  <record>
    <empID>80000000</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>A</FieldName>
    <NewIDorValue>76091</NewIDorValue>
  </record>
    <record>
    <empID>80000001</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>B</FieldName>
    <NewIDorValue>76091</NewIDorValue>
  </record>
</records>

我想基于FieldName对记录进行分组,输出XML应该是

<?xml version='1.0' encoding='UTF-8'?>
<Data>
<records>
  <record>
    <empID>80000000</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>A</FieldName>
    <NewIDorValue>C HACIENDA DEL PEÑASCO 1271</NewIDorValue>
  </record>
  <record>
    <empID>80000000</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>A</FieldName>
    <NewIDorValue>400</NewIDorValue>
  </record>
  <record>
    <empID>80000000</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>A</FieldName>
    <NewIDorValue>76091</NewIDorValue>
  </record>
  </records>
<records>
  <record>
    <empID>80000000</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>B</FieldName>
    <NewIDorValue>PLAZAS DEL SOL1</NewIDorValue>
  </record>
  <record>
    <empID>80000001</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>B</FieldName>
    <NewIDorValue>Querétaro</NewIDorValue>
  </record>
  <record>
    <empID>80000001</empID>
    <code>10</code>
    <Date>2019-01-23</Date>
    <FieldName>B</FieldName>
    <NewIDorValue>76091</NewIDorValue>
  </record>
</records>
</Data>

我知道可以使用XSLT轻松完成,但是我必须使用Groovy来实现。请告知Groovy是否可以做到这一点?请注意,字段“ FieldName”的值未排序。

使用以下代码,我能够按字母顺序对记录进行排序,但不确定如何对这些记录进行分组

import java.util.Properties;
import java.io.InputStream;
import groovy.xml.MarkupBuilder;
import org.jdom.output.XMLOutputter;

for( int i = 0; i < dataContext.getDataCount(); i++ ) {
    InputStream is = dataContext.getStream(i);
    Properties props = dataContext.getProperties(i);

def rootNode = new XmlParser().parse(is);

        def writer = new StringWriter()
        def mkp = new MarkupBuilder(writer)

        mkp.records{
            rootNode.children()
                    .sort{it.FieldName.toString()}
                    .each{ e ->
                        record {
                            empID(e.empID.text())
                            code(e.code.text())
                            Date(e.Date.text())
                            FieldName(e.FieldName.text())
                            NewIDorValue(e.NewIDorValue.text())
                        }

                    }
        }

XMLOutputter outputter = new XMLOutputter();
is = new ByteArrayInputStream(writer.toString().getBytes("UTF-8"));

dataContext.storeStream(is, props);
}

1 个答案:

答案 0 :(得分:1)

使用Groovy有时太容易了……只需使用groupBy而不是对记录进行排序。

rootNode.children().groupBy{it.FieldName.toString()}.each{ group, recs ->
    records {
        recs.each{ e ->
            record {
                empID(e.empID.text())
                code(e.code.text())
                Date(e.Date.text())
                FieldName(e.FieldName.text())
                NewIDorValue(e.NewIDorValue.text())
            }
        }
    }
}

groupBy创建一个以分组标准为键的Map,并以所有匹配元素的List作为值。

def data = [
    [a:"A", b:"foo"],
    [a:"B", b:"bar"],
    [a:"A", b:"wasd"],
    [a:"B", b:"esdf"]
]

assert data.groupBy{it.a} == [
        A:[
            [a:"A", b:"foo"],
            [a:"A", b:"wasd"]
        ],
        B:[
            [a:"B", b:"bar"],
            [a:"B", b:"esdf"]
        ]
    ]