Добавить в корзинуПозвонить
Найти в Дзене
ezmax

Удаление лишней информации из узлов больших XML-файлов "на коленке".

Имеем большой XML-прайс, который невозможно обработать специальным модулем на сайте из-за ограничений хостинга ( в моем случае 320 мегабайт). Выглядит он приблизительно так: <xml_catalog date="2029-04-16 11:32"> <shop> <name>Бананлаб</name> <company>Компания Бананлаб</company> <currencies> <currency id="RUR" rate="1"/> <currency id="USD" rate="76.98"/> </currencies> <categories> <category id="1" uid="1100932" OrderBy="3001251"> KVM-переключатели </category> <category id="2" uid="1100933" OrderBy="11001763">Кабеля</category> <category id="3" uid="199936" parentId="5202" OrderBy="1151">Батарейки Duracell</category> </categories> <offers> <offer id="1" OrderBy="19290"> <uid>1100385</uid> <priceF>46.08</priceF> .... много полей еще .... <currencyId>USD</currencyId> <categoryId>62624</categoryId> <picture> http://serv02.heraboralab.ru/ISAPI/TestISAPI18.dll?34&1&17 </picture> <count>0</count> <name> D-Link DKVM-4U/C2A 4-портовый KVM-переключатель с портами VGA и USB </name> <weight>1.16</wei

Имеем большой XML-прайс, который невозможно обработать специальным модулем на сайте из-за ограничений хостинга ( в моем случае 320 мегабайт). Выглядит он приблизительно так:

<xml_catalog date="2029-04-16 11:32">

<shop>

<name>Бананлаб</name>

<company>Компания Бананлаб</company>

<currencies>

<currency id="RUR" rate="1"/>

<currency id="USD" rate="76.98"/>

</currencies>

<categories>

<category id="1" uid="1100932" OrderBy="3001251">

KVM-переключатели

</category>

<category id="2" uid="1100933" OrderBy="11001763">Кабеля</category>

<category id="3" uid="199936" parentId="5202" OrderBy="1151">Батарейки Duracell</category>

</categories>

<offers>

<offer id="1" OrderBy="19290">

<uid>1100385</uid>

<priceF>46.08</priceF>

.... много полей еще ....

<currencyId>USD</currencyId>

<categoryId>62624</categoryId>

<picture>

http://serv02.heraboralab.ru/ISAPI/TestISAPI18.dll?34&1&17

</picture>

<count>0</count>

<name>

D-Link DKVM-4U/C2A 4-портовый KVM-переключатель с портами VGA и USB

</name>

<weight>1.16</weight>

<Model>DKVM-4U</Model>

<Vendor>D-Link</Vendor>

<length>21.0</length>

</offer>

<offer id="2" OrderBy="19307">

<uid>1100387</uid>

<priceF>9.33</priceF>

.... много полей еще ....

<currencyId>USD</currencyId>

<categoryId>62624</categoryId>

<picture>

http://serv02.heraboralab.ru/ISAPI/TestISAPI18.dll?34&1&17

</picture>

<count>**</count>

<name>

D-Link DKVM-CU3/B1A Кабель KVM длиной 3 м с разъемами VGA и USB

</name>

<weight>0.04</weight>

<Model>DKVM-CU3</Model>

<Vendor>D-Link</Vendor>

<length>41.0</length>

</offer>

<offer id="3" OrderBy="12090">

<uid>1145426</uid>

<priceF>4.13</priceF>

.... много полей еще ....

<currencyId>USD</currencyId>

<categoryId>595273</categoryId>

<picture>

http://serv02.heraboralab.ru/ISAPI/TestISAPI18.dll?59&1&17

</picture>

<count>***</count>

<name>Duracell LR20-2BL (2 шт. в уп-ке)</name>

<weight>0.31</weight>

<Model>LR20-2BL</Model>

<Vendor>Duracell</Vendor>

<length>9.0</length>

</offer>

</offers>

</shop>

</xml_catalog>

Тарифный план на хостинге довольно дохлый, не позволяет забирать много ОЗУ или процессорного времени для обработки таких объемов информации. А мой модуль XML для Opencart довольно прожорлив. Чтобы обработать 100 Мб информации ему требуется 1 Гб оперативной памяти. А поднять тарифный план до таких высот не позволяет молодость бизнеса и великая еврейская мечта.

Итого: решаю, что первым делом необходимо уменьшить обрабатываемый файл за счет удаления позиций с нулевым остатком. Если их нет, то нафига на них тратить ресурсы? Для обработки напишем программу на Python с использованием библиотеки lxml, которая позволяет быстро манипулировать данными в xml-формате.

Итак программка с учетом разных версий Змия:

#! /usr/bin/env python

from __future__ import print_function # works on 2.x and 3.x

from lxml import etree

file_name ='Price.xml'

root = etree.parse(file_name)

for element in root.iterfind('.//offer'):

if (element.findtext('.//count')) == '0':

element.getparent().remove(element)

sourceFile = open('PTest.xml','w')

print(etree.tostring(root), file=sourceFile)

sourceFile.close()

Мой файл ужался до 50 Мб. Многовато все же.

Думаю избавится от лишних полей в карточках описания товара поставщика, в Интернет-магазине клиента информации все же поменьше:

#! /usr/bin/env python

from __future__ import print_function # works on 2.x and 3.x

from lxml import etree

file_name ='Price.xml'

root = etree.parse(file_name)

for element in root.iterfind('.//offer'):

if (element.findtext('.//count')) == '0':

element.getparent().remove(element)

for element in root.iterfind('.//url'):

element.getparent().remove(element)

for element in root.iterfind('.//priceR'):

element.getparent().remove(element)

for element in root.iterfind('.//priceB'):

element.getparent().remove(element)

for element in root.iterfind('.//priceC'):

element.getparent().remove(element)

for element in root.iterfind('.//priceD'):

element.getparent().remove(element)

for element in root.iterfind('.//priceE'):

element.getparent().remove(element)

for element in root.iterfind('.//priceRRP'):

element.getparent().remove(element)

for element in root.iterfind('.//currencyID'):

element.getparent().remove(element)

for element in root.iterfind('.//warranty'):

element.getparent().remove(element)

for element in root.iterfind('.//PN'):

element.getparent().remove(element)

for element in root.iterfind('.//remote'):

element.getparent().remove(element)

for element in root.iterfind('.//volume'):

element.getparent().remove(element)

for element in root.iterfind('.//RussianName'):

element.getparent().remove(element)

for element in root.iterfind('.//DescrUpdated'):

element.getparent().remove(element)

for element in root.iterfind('.//LastCountry'):

element.getparent().remove(element)

for element in root.iterfind('.//LastGTD'):

element.getparent().remove(element)

for element in root.iterfind('.//Colour'):

element.getparent().remove(element)

for element in root.iterfind('.//WarrantyType'):

element.getparent().remove(element)

for element in root.iterfind('.//picture2'):

element.getparent().remove(element)

for element in root.iterfind('.//picture3'):

element.getparent().remove(element)

for element in root.iterfind('.//OutOfProd'):

element.getparent().remove(element)

for element in root.iterfind('.//QtyInPack'):

element.getparent().remove(element)

for element in root.iterfind('.//lenght'):

element.getparent().remove(element)

for element in root.iterfind('.//width'):

element.getparent().remove(element)

for element in root.iterfind('.//height'):

element.getparent().remove(element)

for element in root.iterfind('.//custom'):

element.getparent().remove(element)

for element in root.iterfind('.//Certificate'):

element.getparent().remove(element)

for element in root.iterfind('.//GTIN'):

element.getparent().remove(element)

sourceFile = open('PTest.xml','w')

print(etree.tostring(root), file=sourceFile)

sourceFile.close()

Убрал кучу ненужных полей и получил в итоге файл объемом 17 Мб. Он прекрасно обрабатывается модулем на мощностях хостера.

Но, как говорится - совершенству нет предела. Изучаю метод построчного анализа информации. Думаю можно все это автоматизировать даже силами дохлого хостинга на скриптах, чтобы вручную не обрабатывать на компе прайсы. Но мозг уже с трудом создает новые нейронные связи. Поэтому позже напишу, когда дожму этот вопрос.