xsltproc morto, sem memória

2

Estou tentando dividir um arquivo xml de 13 GB em pequenos arquivos xml de ~ 50 MB com essa folha de estilo XSLT.

Mas esse processo mata o xsltproc depois que eu vejo isso ocupando mais de 1,7 GB de memória (esse é o total no sistema).

Existe alguma maneira de lidar com grandes arquivos XML com xsltproc? Posso mudar minha folha de estilo? Ou devo usar um processador diferente? Ou eu sou apenas S.O.L.?

<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>
    
por David Parks 20.10.2012 / 04:43

2 respostas

1

Este utilitário simples requer que você tenha o módulo Python e python-lxml (libxml2 instalado no sistema) permitirá que você faça stream dos elementos de análise, transforme cada elemento em XSLT e grave-o no arquivo de resultado imediatamente, sem buffer

#!/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')

Ok, esteja ciente de que, se o seu XSLT contiver <xsl:strip-space elements="*"/> , você pode sofrer com esse bug de 2010, link

    
por Marek Sebera 21.03.2017 / 11:49
1

Bem, parece que há uma opção XML de streaming um pouco diferente do XSLT (o xslt requer que o documento inteiro caiba na memória, as linguagens de transformação xml de streaming não).

Em vez de reescrever o XSLT, que acabei de passar um dia preparando, criei uma instância spot da AWS com 64 GB de memória RAM, dei-lhe algumas trocas e meu XML de 13 GB consumiu apenas 65 GB de RAM xsltproc.

Neste sistema ele funcionava, mas agora posso dizer que você não obterá muito mais do que um arquivo de 13GB da maior instância de alta memória da Amazon. Você precisará de outra solução, como a transmissão de transformações XML.

Como referência para qualquer pessoa que esteja pensando em empurrar o envelope. Essa transformação falhou em uma instância com 32 GB de RAM e partição de swap de 120G. Parece que você pode trocar alguns shows, mas não muito antes de encontrar algum problema que irá travá-lo.

    
por David Parks 20.10.2012 / 07:09