XSL转换300M与xsltproc(内存不足)

时间:2017-01-05 17:08:13

标签: xslt

我需要转换XML文件(将PRODUCTNO设置为所有ITEM元素的ITEM_ID)。没有新行,文件内容是一条长行。

var $array = {
    "firstVar" : 1,
    "secondVar" : this.firstVar + 1
};

console.log($array.firstVar); //1
console.log($array.secondVar); //NaN

首先尝试使用xsltproc,但最后以300M文件“kill”(memmory,消耗2G)结束。

<SHOP>
<ITEM>
  <NAME>...</NAME>
  <ITEM_ID>11</ITEM_ID>
  <PRODUCTNO>22</PRODUCTNO>
  <TAG>...</TAG>
</ITEM>
....
</SHOP

好吧,我今天学习XSL :)是否可以更好地编写它(更高效的内存),或者必须使用其他处理器。由于逐行处理,我尝试sed没有成功。

<?xml version='1.0' encoding='ISO-8859-1'?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="ITEM_ID">
  <ITEM_ID><xsl:value-of select = "../PRODUCTNO" /></ITEM_ID>
 </xsl:template>

</xsl:stylesheet>

Xsl处理器会更好。

2 个答案:

答案 0 :(得分:2)

Martin Honnen关于XSL 3.0的答案是正确的!
最后,由于许可证,我使用了SED

我的解决方案是:

  1. 将每个项目放在一行
  2. 做替换(ITEM_ID总是在PRODUCTNO
  3. 前面

    所以SED解决方案看起来像:

    cat file.xml | sed -e 's/<ITEM>/\n<ITEM>/g' | sed -e 's/<ITEM_ID>(.*)<\/ITEM_ID>(.*)<PRODUCTNO>(.*)<\/PRODUCTNO>/<ITEM_ID>\3</ITEM_ID>\2<PRODUCTNO>\3<\/PRODUCTNO>/g'
    

    它不像SLT处理那么安全,但速度/内存消耗会赢。

答案 1 :(得分:1)

使用流式传输和复制的混合,您可以使用

在XSLT 3.0中解决它
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:param name="STREAMABLE" static="yes" as="xs:boolean" select="true()"/>

    <xsl:mode _streamable="{$STREAMABLE}" on-no-match="shallow-copy"/>

    <xsl:mode name="change" on-no-match="shallow-copy"/>

    <xsl:template match="ITEM">
        <xsl:apply-templates select="copy-of()" mode="change"/>
    </xsl:template>

    <xsl:template match="ITEM_ID" mode="change">
        <xsl:copy>
            <xsl:value-of select="../PRODUCTNO"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

以流模式处理初始输入文档,然后创建每个ITEM元素的副本,以使用常规模板匹配来转换ITEM_ID

要使用XSLT 3.0和流媒体,您需要使用Saxon 9.7 EE(可从http://www.saxonica.com/download/download_page.xml获得)或Exselt(可从http://exselt.net/获得)。

另一方面,如果您可以在当今的桌面PC上为其提供足够的内存,那么使用普通的XSLT 1.0或2.0处理器可以实现300 MB的声音。