Как обработать каждую строку CSV в один вывод XML - WSO2/Smooks

TL;DR: у меня есть многострочный CSV-файл, и я хочу обрабатывать его построчно и генерировать разные XML-файлы для каждой строки.

У меня есть следующий файл CSV:

Chathuri,Wimalasena,Female,25,SriLanka
Saminda,Wijerathne,Male,26,SriLanka
Dakshitha,Rathnayaka,Female,24,SriLanka
Harsha,Martin,Male,24,SriLanka

В настоящее время я использую smooks и делаю следующее преобразование:

<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
        <people>
                <person>
                <lastname>Wimalasena</lastname>
                <firstname>Chathuri</firstname>
                <gender>Female</gender>
                <age>25</age>
                <country>SriLanka</country>
            </person>
            <person>
                <lastname>Wijerathne</lastname>
                <firstname>Saminda</firstname>
                <gender>Male</gender>
                <age>26</age>
                <country>SriLanka</country>
            </person>
            <person>
                <lastname>Rathnayaka</lastname>
                <firstname>Dakshitha</firstname>
                <gender>Female</gender>
                <age>24</age>
                <country>SriLanka</country>
            </person>
            <person>
                <lastname>Martin</lastname>
                <firstname>Harsha</firstname>
                <gender>Male</gender>
                <age>24</age>
                <country>SriLanka</country>
            </person>
        </people>
    </soapenv:Body>
</soapenv:Envelope>

Вопросы: я хочу что-то вроде этого:

<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
        <people>
            <person>
                <lastname>Wimalasena</lastname>
                <firstname>Chathuri</firstname>
                <gender>Female</gender>
                <age>25</age>
                <country>SriLanka</country>
            </person>
        </people>
    </soapenv:Body>
</soapenv:Envelope>


<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
        <people>
            <person>
                <lastname>Wijerathne</lastname>
                <firstname>Saminda</firstname>
                <gender>Male</gender>
                <age>26</age>
                <country>SriLanka</country>
            </person>
        </people>
    </soapenv:Body>
</soapenv:Envelope>

Мой smook.xml:

<?xml version="1.0" encoding="UTF-8"?><smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:csv="http://www.milyn.org/xsd/smooks/csv-1.2.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
  <params>
    <param name="stream.filter.type">SAX</param>
    <param name="inputType">input.csv</param>
    <param name="input.csv" type="input.type.actived">File:/C:\Users\victor.viola\Desktop\test.csv</param>
    <param name="default.serialization.on">true</param>
  </params>
  <csv:reader fields="name,surname,gender,age,country"/>
  <ftl:freemarker applyOnElement="#document">
    <ftl:template><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<people>
    <#list .vars["csv-set"]["csv-record"] as csv_record>
    <person>
        <lastname>${.vars["csv_record"]["surname"]}</lastname>        
        <firstname>${.vars["csv_record"]["name"]}</firstname>        
        <gender>${.vars["csv_record"]["gender"]}</gender>        
        <age>${.vars["csv_record"]["age"]}</age>        
        <country>${.vars["csv_record"]["country"]}</country>        
    </person>
    </#list>    
</people>]]></ftl:template>
    <param name="rootElementName">people</param>
    <param name="modelSrc">File:/C:\Users\victor.viola\Desktop\example.xsd</param>
    <param name="modelSrcType">XSD</param>
    <param name="messageType">XML</param>
    <param name="templateDataProvider">input</param>
  </ftl:freemarker>
  <resource-config selector="#document">
    <resource>org.milyn.delivery.DomModelCreator</resource>
  </resource-config>
</smooks-resource-list>

person Victor Viola    schedule 04.02.2016    source источник
comment
Не имеет отношения к вопросу, но вместо .vars["csv_record"]["surname"] можно просто написать csv_record.surname. .vars["csv-set"]["csv-record"] сложнее из-за -: csv\-set.csv\-record (для \- требуется FreeMarker 2.3.22+).   -  person ddekany    schedule 05.02.2016
comment
Спасибо за подсказку =)   -  person Victor Viola    schedule 05.02.2016


Ответы (1)


С помощью smooks вы можете направлять сообщения в файлы или очереди JMS.

Пожалуйста, взгляните на этот пример, который читает файл в потоковом режиме и разбивает его содержимое на файлы или сообщения JMS (он работает с фиксированной длиной, но то же самое с csv, просто используйте csv:reader)

Прокси-сервис:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="VFSProxy" transports="vfs" startOnLoad="true" trace="disable">
    <target>
        <inSequence>
            <property name="DISABLE_SMOOKS_RESULT_PAYLOAD" value="true"/>
            <smooks config-key="SmooksSplitFileFL">
            <!--smooks config-key="SmooksSplitJMSFL"-->
                <input type="text"/>
                <output type="xml"/>
            </smooks>
        </inSequence>
    </target>
    <parameter name="transport.vfs.FileURI">vfs:file:///C:/In</parameter>
    <parameter name="transport.vfs.FileNamePattern">.*.fl</parameter>
    <parameter name="transport.vfs.ContentType">text/plain</parameter>
    <parameter name="transport.vfs.Streaming">true</parameter>
    <parameter name="transport.PollInterval">15</parameter>
    <parameter name="transport.vfs.ActionAfterProcess">DELETE</parameter>
    <parameter name="transport.vfs.ActionAfterFailure">DELETE</parameter>
</proxy>

Smooks, которые разбиваются на файлы (локальная запись, имя используется для имени файла, поэтому, если есть несколько строк с одинаковым именем, у вас будет последняя)

<?xml version="1.0" encoding="UTF-8"?>
<localEntry xmlns="http://ws.apache.org/ns/synapse" key="SmooksSplitFileFL">
    <smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd" xmlns:fl="http://www.milyn.org/xsd/smooks/fixed-length-1.3.xsd" xmlns:file="http://www.milyn.org/xsd/smooks/file-routing-1.1.xsd">
        <params>
            <param name="stream.filter.type">SAX</param>
            <param name="default.serialization.on">false</param>
        </params>
        <fl:reader fields="LASTNAME[2],FIRSTNAME[10]" skipLines="0"/>
        <resource-config selector="record">
            <resource>org.milyn.delivery.DomModelCreator</resource>
        </resource-config>
        <file:outputStream openOnElement="record" resourceName="fileSplitStream">
            <file:fileNamePattern>${.vars["record"].LASTNAME}.xml</file:fileNamePattern>
            <file:destinationDirectoryPattern>C:\Processed</file:destinationDirectoryPattern>
            <file:highWaterMark mark="-1"/>
        </file:outputStream>
        <ftl:freemarker applyOnElement="record">
            <ftl:template>/repository/resources/smooks/RecordToXML.ftl</ftl:template>
            <ftl:use>
                <ftl:outputTo outputStreamResource="fileSplitStream"/>
            </ftl:use>
        </ftl:freemarker>
    </smooks-resource-list>
    <description/>
</localEntry>

Smooks, которые разбиваются на сообщения JMS

<?xml version="1.0" encoding="UTF-8"?>
<localEntry xmlns="http://ws.apache.org/ns/synapse" key="SmooksSplitJMSFL">
    <smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd" xmlns:fl="http://www.milyn.org/xsd/smooks/fixed-length-1.3.xsd" xmlns:jms="http://www.milyn.org/xsd/smooks/jms-routing-1.2.xsd">
        <params>
            <param name="stream.filter.type">SAX</param>
            <param name="default.serialization.on">false</param>
        </params>
        <fl:reader fields="LASTNAME[2],FIRSTNAME[10]" skipLines="0"/>
        <resource-config selector="record">
            <resource>org.milyn.delivery.DomModelCreator</resource>
        </resource-config>
        <jms:router routeOnElement="record" beanId="Person" destination="dynamicQueues/TestFL">
            <jms:connection factory="QueueConnectionFactory"/>
            <jms:jndi contextFactory="org.apache.activemq.jndi.ActiveMQInitialContextFactory" providerUrl="nio://localhost:61616"/>
            <jms:highWaterMark mark="-1"/>
        </jms:router>
        <ftl:freemarker applyOnElement="record">
            <ftl:template>/repository/resources/smooks/RecordToXML.ftl</ftl:template>
            <ftl:use>
                <ftl:bindTo id="Person"/>
            </ftl:use>
        </ftl:freemarker>
    </smooks-resource-list>
    <description/>
</localEntry>

Шаблон (создайте файл ESB_HOME/repository/resources/smooks/RecordToXML.ftl):

<#assign rec = .vars["record"]>
<person>
    <lastname>${rec.LASTNAME}</lastname>
    <firstname>${rec.FIRSTNAME}</firstname>
</person>
person Jean-Michel    schedule 05.02.2016
comment
Спасибо и хорошего дня. - person Victor Viola; 05.02.2016
comment
Когда я пытаюсь заменить FL на CSV Reader, мой файл просто исчезает, и ничего не происходит, даже лога. РЖУ НЕ МОГУ - person Victor Viola; 05.02.2016
comment
В моем прокси-сервере ActionAfterProcess и сбой DELETE, поэтому я предполагаю, что проблема с вашей конфигурацией, и файл удален. Что с логами esb? - person Jean-Michel; 05.02.2016
comment
с csv вы должны адаптировать конфигурацию smooks, например: resource-config selector=record становится resource-config selector=csv-record (дерево xml не то же самое). Это должно быть похоже на applyOnElement=record в ftl:freemarker и routeOnElement=record в jms:router или openOnElement=record в файле:outputStream. - person Jean-Michel; 05.02.2016
comment
Спасибо @ Жан-Мишель, я это заметил. Я пытаюсь исправить прямо сейчас. - person Victor Viola; 05.02.2016
comment
(Снова ненужное использование .vars[...]... странно.) - person ddekany; 05.02.2016