Как вставить файл CSV в вывод XML - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь преобразовать CSV (файл, разделенный запятыми) в XML, используя XSLT.

CSV Образец:

AcctEntryId,ValueDate,Entity,Folder,DenomCcy,FunctCcy
321,2017-08-29,ABC NY,My Portfolio/PAC,BR,US
322,2017-08-30,ABC NY,My Portfolio/PBC,BR,US
323,2017-08-31,ABC NY,My Portfolio/PCC,BR,US

Требуемый вывод XML:

<?xml version="1.0" encoding="utf-8"?>
<ProcessResponse xmlns="http://com.test.ws/">
    <ProcessResult>&lt;Data DataNodeName="CData" DataType="TEXT"&gt;&lt;CData&gt;&lt;![CDATA[AcctEntryId,ValueDate,Entity,Folder,DenomCcy,FunctCcy
        321,2017-08-29,ABC NY,My Portfolio/PAC,BR,US
        322,2017-08-30,ABC NY,My Portfolio/PBC,BR,US
        323,2017-08-31,ABC NY,My Portfolio/PCC,BR,US
        ]]&gt;&lt;/CData&gt;&lt;/Data&gt;
    </ProcessResult>
</ProcessResponse>

Я хочу выбрать файл CSV из папки AL11 в sap. Окончательный вывод после сопоставления xslt, я хочу, чтобы это был файл XML в нужном формате, указанном выше.

Подскажите, пожалуйста, как мне кодировать XSLT для генерации вышеуказанного XML на основе данных CSV.

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Вот способ конвертировать CSV в XML без XSLT. Требуемый XML довольно примитивен, поскольку имеет только один дочерний узел, поэтому я считаю, что XSLT здесь избыточен.

DATA: lv_data     TYPE string,
      lv_filename TYPE string VALUE 'C:\usr\sap\erp\sys\src\sample.csv',
      lv_csv      TYPE string.

OPEN DATASET lv_filename FOR INPUT IN TEXT MODE ENCODING DEFAULT.

WHILE sy-subrc = 0.
READ DATASET lv_filename INTO lv_data.
CHECK strlen( lv_data ) > 0.
lv_csv = lv_csv && lv_data && cl_abap_char_utilities=>cr_lf.
NDWHILE.
CLOSE DATASET lv_filename.

DATA(lo_ixml) = cl_ixml=>create( ).
DATA(lo_response) = lo_ixml->create_document( ).
DATA(lo_result)  = lo_response->create_simple_element( name    = 'ProcessResponse' parent  = lo_response ).

CONCATENATE `&lt;Data DataNodeName="CData" DataType="TEXT"&gt;&lt;CData&gt;&lt;![CDATA[`
v_csv `]]&gt;&lt;/CData&gt;&lt;/Data&gt;` INTO lv_csv.

o_response->create_simple_element( name    = 'ProcessResult' parent  = lo_result value   = lv_csv ).

DATA(lo_streamfactory) = lo_ixml->create_stream_factory( ).
DATA(lo_ostream)  = lo_streamfactory->create_ostream_uri( system_id = 'C:\usr\sap\erp\sys\src\sample.xml' ).
DATA(lo_renderer) = lo_ixml->create_renderer( ostream  = lo_ostream document = lo_response ).
DATA(ref_ixml_encoding) = lo_ixml->create_encoding( byte_order    = 0 character_set = 'UTF-8' ).

o_ostream->set_encoding( encoding = ref_ixml_encoding ).
o_ostream->set_pretty_print( 'X' ).
o_renderer->render( ).

Просто запустите этот фрагмент, если ваш CSV лежит в C:\usr\sap\erp\sys\src\ dir и полученный XML будет помещен в тот же dir.

0 голосов
/ 16 января 2019

Это решение XSLT-2.0 или выше. Я не знаю, поддерживает ли SAP это. Если нет, см. Ниже для взлома XSLT-1.0.

Вы можете использовать функцию XSLT-2.0 unparsed-text() в сочетании с функцией RegEx xsl:analyze-string:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:variable name="csv" select="replace(unparsed-text('file:///home/kubuntu/Downloads/a.csv'),'utf-8','')"/>

    <xsl:template match="/">
        <xsl:element name="ProcessResponse" namespace="http://com.test.ws/">
            <xsl:element name="ProcessResult" namespace="http://com.test.ws/">
                <xsl:value-of select="'&lt;Data DataNodeName=&quot;CData&quot; DataType=&quot;TEXT&quot;&gt;&lt;CData&gt;&lt;![CDATA['" />
                <xsl:analyze-string select="$csv" regex='(.+)\n'>
                    <xsl:matching-substring>
                        <xsl:value-of select="concat(regex-group(1),'&#xa;')" />
                    </xsl:matching-substring>
                    <xsl:non-matching-substring><xsl:sequence select="."/></xsl:non-matching-substring>
                </xsl:analyze-string>
                <xsl:value-of select="']]&gt;&lt;/CData&gt;&lt;/Data&gt;&#xa;'" />
            </xsl:element>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Вывод по желанию, хотя его требование кажется мне немного странным ...

<?xml version="1.0" encoding="UTF-8"?>
<ProcessResponse xmlns="http://com.test.ws/">
   <ProcessResult>&lt;Data DataNodeName="CData" DataType="TEXT"&gt;&lt;CData&gt;&lt;![CDATA[AcctEntryId,ValueDate,Entity,Folder,DenomCcy,FunctCcy
321,2017-08-29,ABC NY,My Portfolio/PAC,BR,US
322,2017-08-30,ABC NY,My Portfolio/PBC,BR,US
323,2017-08-31,ABC NY,My Portfolio/PCC,BR,US
]]&gt;&lt;/CData&gt;&lt;/Data&gt;
</ProcessResult>
</ProcessResponse>

Если вы ограничены XSLT-1.0, вы можете использовать Entity Reference в качестве хака, как описано в этом ответе SO .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...