簡體   English   中英

XSLT 1.0:CSV到XML-如何分割和征服

[英]XSLT 1.0: CSV to XML - How to divide and conquer

在從堆棧溢出答案中獲得大量參考之后,我得到了以下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的性能?

在這種情況下,使用XSLT執行分而治之並非易事。 有多種方法可以優化XSLT處理,您可能需要嘗試使用其他處理器來處理不同的事情,但是您的代碼不容易改進,因為它實際上不執行任何XML處理。 它在一個包含字符串的大單個元素節點上運行。 實際上,您僅使用XPath函數來解析字符串和XSLT變量來存儲它們。 消除XSLT開銷將更加有效。

您的選擇包括:

  1. 增加您的內存(使用-Xmx選項)。
  2. 將您的文件分成較小的部分(需要使用格式良好的XML),然后在XSLT中分別處理每個部分。

但是XSLT無法為您提供選項no。 2,由於要開始處理文件,因此需要將其全部加載到內存中。 由於每個片段都必須是格式正確的XML,因此它無法加載部分文本並將其拆分。 因為您只有一個節點,所以甚至連SAX解析器都沒有那么高效。 最好使用高效的字符串解析器,在其中可以拆分CSV,然后將每個片段包裝在XML標記中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM