Как сгруппировать записи XML на основе имени поля groovy - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть требование, в котором мне нужно прочитать входной 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 голосов
/ 27 февраля 2019

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"]
        ]
    ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...