Я пытаюсь разделить 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() < $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>
</xsl:text>
</xsl:for-each>
</doc>
</xsl:for-each>
</add>
</exsl:document>
</xsl:template>
Эта простая утилита, требует, чтобы Вы, чтобы иметь модуль 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
Что ж, похоже, есть опция потоковой передачи XML, которая немного отличается от XSLT (xslt требует, чтобы весь документ помещался в память, а языки потоковой трансформации XML - нет).
Вместо того, чтобы переписывать XSLT, который я только что потратил на подготовку дня, я просто развернул спотовый экземпляр AWS с 64 ГБ оперативной памяти, дал ему некоторый обмен, и мой 13 ГБ XML-файл потреблял всего около 65 ГБ оперативной памяти под xsltproc.
В этой системе она работала, но теперь я могу сказать вам, что вы не получите намного больше, чем 13 ГБ файл даже из самого большого экземпляра Amazon с большой памятью. Вам понадобится другое решение, такое как потоковые преобразования XML.
В качестве ориентира для тех, кто думает о том, чтобы раздвинуть конверт. Это преобразование не удалось выполнить в экземпляре с 32 ГБ ОЗУ и разделом подкачки 120 ГБ. Кажется, что вы можете поменять несколько концертов, но не слишком много, прежде чем столкнетесь с какой-то проблемой, которая приведет к сбою.