[英]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="' '" />
<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問題中進行分而治之的參考,但是我不知道如何將字符串分成兩半。
所以我的問題是:
在這種情況下,使用XSLT執行分而治之並非易事。 有多種方法可以優化XSLT處理,您可能需要嘗試使用其他處理器來處理不同的事情,但是您的代碼不容易改進,因為它實際上不執行任何XML處理。 它在一個包含字符串的大單個元素節點上運行。 實際上,您僅使用XPath函數來解析字符串和XSLT變量來存儲它們。 消除XSLT開銷將更加有效。
您的選擇包括:
-Xmx
選項)。 但是XSLT無法為您提供選項no。 2,由於要開始處理文件,因此需要將其全部加載到內存中。 由於每個片段都必須是格式正確的XML,因此它無法加載部分文本並將其拆分。 因為您只有一個節點,所以甚至連SAX解析器都沒有那么高效。 最好使用高效的字符串解析器,在其中可以拆分CSV,然后將每個片段包裝在XML標記中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.