xsltproc 已终止,内存不足

xsltproc 已终止,内存不足

我正在尝试使用此 XSLT 样式表将 13GB 的 xml 文件拆分为约 50MB 的小 xml 文件。

但是当我发现 xsltproc 占用了超过 1.7GB 的内存(这是系统的总内存量)后,该进程就终止了。

有没有办法用 xsltproc 处理巨大的 XML 文件?我可以更改样式表吗?还是我应该使用其他处理器?还是我只是 SOL?

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:exsl="http://exslt.org/common"
                extension-element-prefixes="exsl"
                xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="block-size" select="75000"/>

<xsl:template match="/">
        <xsl:copy>
                <xsl:apply-templates select="mysqldump/database/table_data/row[position() mod $block-size = 1]" />
        </xsl:copy>
</xsl:template>

<xsl:template match="row">
        <exsl:document href="chunk-{position()}.xml">
        <add>
                <xsl:for-each select=". | following-sibling::row[position() &lt; $block-size]" >
                <doc>
                        <xsl:for-each select="field">
                        <field>
                                <xsl:attribute name="name"><xsl:value-of select="./@name"/></xsl:attribute>
                                <xsl:value-of select="."/>
                        </field>
                        <xsl:text>&#xa;</xsl:text>
                        </xsl:for-each>
                </doc>
                </xsl:for-each>
        </add>
        </exsl:document>
</xsl:template>

答案1

这个简单的实用程序要求您有 Python 和 python-lxml 模块(系统中安装了 libxml2),它将允许您流式解析元素,通过 XSLT 转换每个元素并立即将其写入结果文件,无需缓冲

#!/usr/bin/env python3

from lxml import etree
import re

_xslt = etree.parse('FILL_XSLT_DOC')
_dom = etree.iterparse('FILL_SOURCE_XML')
transform = etree.XSLT(_xslt)
results = open('FILL_RESULT_XML','w+b')

for elem in _dom:
    if (elem[1].tag.endswith('FILL_SEARCHED_ELEMENT_NAME')):
        newElem = transform(elem[1])
        #print(etree.tostring(newElem,xml_declaration = False,encoding='utf8'))
        results.write(etree.tostring(newElem,xml_declaration = False,encoding='utf8'))
        results.write(b'\n')

好的,请注意,如果您的 XSLT 包含<xsl:strip-space elements="*"/>此 2010 年错误,您可能会受到影响,https://bugs.launchpad.net/lxml/+bug/583249

答案2

嗯,似乎有一个流式 XML 选项,它与 XSLT 有点不同(xslt 要求整个文档放入内存,而流式 xml 转换语言则不需要)。

我没有重写刚刚花了一天时间准备的 XSLT,而是启动了一个具有 64 GB RAM 的 AWS 现货实例,给它一些交换,而我的 13GB XML 在 xsltproc 下消耗了大约 65GB 的 RAM。

它可以在此系统上运行,但我现在可以告诉你,即使是亚马逊最大的高内存实例,你也无法从中获得超过 13GB 的文件。你需要采用另一种解决方案,例如流式 XML 转换。

作为任何想要突破极限的人的基准。此转换在具有 32 GB RAM 和 120G 交换分区的实例上失败。似乎您可以交换几 GB,但不要交换太多,否则会遇到一些会导致其崩溃的问题。

相关内容