当前位置: 首页 > 知识库问答 >
问题:

XSLT 1.0:CSV到XML--如何分而治之

姚永年
2023-03-14

在大量引用堆栈溢出答案之后,我有了以下XSL,它使用列标题作为每个相应单元格的节点名,将CSV转换为XML。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    exclude-result-prefixes="xsl">
    <xsl:output method="xml" encoding="utf-8" />

    <xsl:variable name="newline" select="'&#10;'" />
    <xsl:variable name="comma" select="','" />
    <xsl:variable name="csv" select="." />
    <xsl:variable name="fields" select="substring-before( concat( $csv, $newline ), $newline )" />

    <xsl:template match="/">
        <xsl:element name="EXCHANGE">
            <xsl:element name="DDM">
                <xsl:call-template name="write-row">
                    <xsl:with-param name="rows" select="substring-after( $csv, $newline)"/>
                </xsl:call-template>
            </xsl:element>
        </xsl:element>
    </xsl:template>

    <xsl:template name="write-row">
        <xsl:param name="rows"/>

        <xsl:variable name="this-row" select="substring-before( concat( $rows, $newline ), $newline )" />
        <xsl:variable name="remaining-rows" select="substring-after( $rows, $newline )" />

        <xsl:if test="string-length($this-row) > 1">
            <xsl:element name="DDMSRS">
                <xsl:call-template name="write-item">
                    <xsl:with-param name="columns" select="$fields"/>
                    <xsl:with-param name="row" select="$this-row" />
                </xsl:call-template>
            </xsl:element>
        </xsl:if>

        <xsl:if test="string-length( $remaining-rows ) > 0">
            <xsl:call-template name="write-row">
                <xsl:with-param name="rows" select="$remaining-rows" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>


    <xsl:template name="write-item">
        <xsl:param name="row"/>
        <xsl:param name="columns"/>

        <xsl:variable name="col" select="substring-before( concat( $columns, $comma ), $comma)" />
        <xsl:variable name="remaining-items" select="substring-after( $row, $comma )" />
        <xsl:variable name="remaining-columns" select="substring-after( $columns, $comma )" />

        <xsl:if test="$col != ''">
            <xsl:element name="{$col}">
                <xsl:value-of select="substring-before( concat( $row, $comma ), $comma)" /> 
            </xsl:element>
        </xsl:if>

        <xsl:if test="string-length( $remaining-items ) > 0">
            <xsl:call-template name="write-item">
                <xsl:with-param name="columns" select="$remaining-columns"/>
                <xsl:with-param name="row" select="$remaining-items" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

在csv上运行XSL如下所示(换行符是行分隔符):

<root><![CDATA[COL_HEAD1,COL_HEAD2,COL_HEAD3
123456789,Peter,My address
]]></root>

将返回以下XML:

<?xml version="1.0" encoding="utf-8"?>
<EXCHANGE>
    <DDM>
        <DDMSRS>
            <COL_HEAD1>123456789</COL_HEAD1>
            <COL_HEAD2>Peter</COL_HEAD2>
            <COL_HEAD3>My address</COL_HEAD3>
        </DDMSRS>
    </DDM>
</EXCHANGE>

我现在遇到的问题是,当我想在csv(1000或更多)中处理大量行时,我会耗尽内存。

我在其他stackoverflow问题中看到了分而治之的提法,但我不知道如何将字符串一分为二。

所以我的问题是:

  1. 如何在此方案中执行分而治之?
  2. 是否有其他使用XSLT 1.0提高此XSL性能的方法?

共有1个答案

越雨泽
2023-03-14

在此场景中使用XSLT执行分而治之并不简单。有很多方法可以优化XSLT处理,您可能希望尝试一个不同的处理器,它可以做不同的事情,但是您的代码不容易改进,因为它实际上不做任何XML处理。它对包含字符串的一个大的单个元素节点进行操作。您实际上只是使用XPath函数来解析字符串,并使用XSLT变量来存储字符串。排除XSLT开销会更有效。

您的选项包括:

  1. 增加内存(使用-xmx选项)。
  2. 将文件分解为更小的部分(这些部分需要格式良好的XML),并在XSLT中分别处理每个部分。

但是XSLT不能帮助您使用选项No。2,因为要开始处理您的文件,需要将其全部加载到内存中。它不能加载部分文本并将其拆分,因为每个片段必须是格式良好的XML。即使是SAX解析器也没有那么高效,因为您只有一个节点。最好使用高效的字符串解析器,在这里可以拆分CSV,然后将每个片段包装在XML标记中。

 类似资料:
  • 在分而治之的方法中,手头的问题被分成较小的子问题,然后每个问题都独立解决。 当我们继续将子问题划分为更小的子问题时,我们最终可能会达到无法进行更多划分的阶段。 解决那些“原子”最小可能的子问题(分数)。 最后合并所有子问题的解决方案以获得原始问题的解决方案。 从广义上讲,我们可以通过三个步骤来理解divide-and-conquer方法。 Divide/Break 此步骤涉及将问题分解为更小的子问

  • 在本章中,我们将创建一个使用CSV Reader和XML Writer的简单Spring Batch应用程序。 阅读器 - 在应用程序中使用的阅读器是,用于从CSV文件中读取数据。 以下是在此应用程序中使用的输入CSV文件。 本文档包含指定详细信息的数据记录,如教程编号,教程作者,教程标题,提交日期,教程图标和教程说明。 完整的项目目录结构如下: 创建一个Maven项目,使用以下配置文件(pom.

  • 所以我试图转换一个. xml数据源: 转换成. csv但以这种格式格式化 我有重复的元素,比如“title”、“description”等,我想将它们从完全垂直的xml格式中提取出来,并将每个元素分解成一个单独的列。 我发现了一个工具,我相信它确实可以做到这一点,但我不知道如何设置它 我有两个文件——a。蝙蝠和。罐子在内部。bat我们有以下默认代码: 我不知道该怎么修改这个。有谁能提供一些建议吗?

  • 本文向大家介绍C#递归算法之分而治之策略,包括了C#递归算法之分而治之策略的使用技巧和注意事项,需要的朋友参考一下 1.分而治之的概念       分而治之是一种使用递归解决问题的算法,主要的技巧是将一个大的复杂的问题划分为多个子问题,而这些子问题可以作为终止条件,或者在一个递归步骤中得到解决,所有子问题的解决结合起来就构成了对原问题的解决 2.分而治之的优点和缺点   分而治之算法通常包括一个或

  • 假设坐标(x1,y1)上的一个点支配另一个点(x2,y2)如果x1≤x2,y1≤y2; 我有一组点(x1,y1),...(xn,yn),我想找到支配对的总数。我可以通过比较所有点来使用蛮力,但这需要时间O(n2)。相反,我想使用分而治之的方法在时间O(n log n)中解决这个问题。 现在,我有以下算法: 所以y坐标的两个半部分是:{1,3,4,5,5}和{5,8,9,10,12} 我画分界线。

  • 这是我想做的, 这是我的spend.csv文件: 从表视图: csv的表格视图 这是我想要的输出文件,名为spend.xml: 为了做到这一点,我在这里和那里找到了一些东西,并设法得到了这个: 此时,程序应该在终端中打印XML文件,但是; 遗憾的是,由于我的CSV文件中每个值都有双引号,我遇到了这个问题: java组织。w3c。多姆。DOMEException invalid_character_