Dividir arquivo com base na tag XML inicial e final

Dividir arquivo com base na tag XML inicial e final

A divisão pode ser usada para dividir um arquivo em vários segmentos onde o tamanho de cada segmento é baseado no número de correspondências de um elemento XML?

Por exemplo, para a divisão XML abaixo quando encontros de "<test xsi:type="update" locale="en_US">"é 2

<?xml version="1.0" encoding="UTF-8"?>
<testers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
</testers>

A divisão do arquivo XML acima deve gerar 2 arquivos.

arquivo1:

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

e arquivo 2 contendo apenas uma única entrada:

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

Aqui está o que estou tentando:

split -p "<test xsi:type=\"update\" locale=\"en_US\">" test.xml segment

que gera 4 arquivos:

segmentaa :

<?xml version="1.0" encoding="UTF-8"?>
<testers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

segmentab :

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

segmentar :

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

segmentado :

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
</testers>

Pode splitser utilizado da maneira que estou sugerindo. O arquivo que estou processando tem 40GB, utilizo o exemplo acima para ilustrar o problema que estou tentando resolver.

Responder1

Eu não acho que seja possível com split. Você poderia usar awk:

awk '
  BEGIN{ 
    fmt="segment%02d"               # 2 digits for suffix, zero padded
    start="<test xsi:type=\"update\" locale=\"en_US\">"
    end="</test>"
  }
  $0 == start, $0 == end{
    if ($0 == start && ++cnt%2==1){ # for every 2nd start element...
      fname=sprintf(fmt, fcnt++)    # update output filename
    }
    print $0 > fname                # print line, redirect output to fname
  }
' test.xml

Isso produz dois arquivos segment00e segment01:

$ head segment*
==> segment00 <==
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

==> segment01 <==
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

informação relacionada