xsltproc убит, недостаточно памяти

Я пытаюсь разделить 13ГБ XML-файл на небольшие ~ 50 МБ XML-файлы с помощью этой таблицы стилей XSLT.

Но этот процесс убивает xsltproc после того, как я вижу, что он занимает более 1,7 ГБ памяти (это всего в системе).

Есть ли способ справиться с огромными файлами XML с помощью xsltproc? Могу ли я изменить свою таблицу стилей? Или я должен использовать другой процессор? Или я просто С.О.Л.?

<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>
2
задан 20 October 2012 в 06:43

2 ответа

Эта простая утилита, требует, чтобы Вы, чтобы иметь модуль 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 / + ошибка/583249

1
ответ дан 20 October 2012 в 06:43

Что ж, похоже, есть опция потоковой передачи XML, которая немного отличается от XSLT (xslt требует, чтобы весь документ помещался в память, а языки потоковой трансформации XML - нет).

Вместо того, чтобы переписывать XSLT, который я только что потратил на подготовку дня, я просто развернул спотовый экземпляр AWS с 64 ГБ оперативной памяти, дал ему некоторый обмен, и мой 13 ГБ XML-файл потреблял всего около 65 ГБ оперативной памяти под xsltproc.

В этой системе она работала, но теперь я могу сказать вам, что вы не получите намного больше, чем 13 ГБ файл даже из самого большого экземпляра Amazon с большой памятью. Вам понадобится другое решение, такое как потоковые преобразования XML.

В качестве ориентира для тех, кто думает о том, чтобы раздвинуть конверт. Это преобразование не удалось выполнить в экземпляре с 32 ГБ ОЗУ и разделом подкачки 120 ГБ. Кажется, что вы можете поменять несколько концертов, но не слишком много, прежде чем столкнетесь с какой-то проблемой, которая приведет к сбою.

0
ответ дан 20 October 2012 в 06:43

Другие вопросы по тегам:

Похожие вопросы: