首页 > 解决方案 > 如何在 XML 输出中嵌入 CSV 文件

问题描述

我正在尝试使用 XSLT 将 CSV(逗号分隔文件)转换为 XML。

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>

我想从 sap 的 AL11 文件夹中选择 CSV 文件。xslt 映射后的最终输出,我希望它是上面指定的所需格式的 XML 文件。

请您指导我如何编写 XSLT 代码以根据示例 CSV 数据生成上述 XML。

标签: xmlcsvxsltsap

解决方案


这是一个 XSLT-2.0 或更高版本的解决方案。我不知道 SAP 是否支持这一点。如果没有,请参阅下面的 XSLT-1.0 hack。

您可以将 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,则可以使用实体引用作为 hack ,如此 SO answer 中所述。


推荐阅读