Функции разборщика xml


Содержание

имеет больший вес, чем тег

в данном конкретном документе, потому что используя CSS я могу добиться прямо противоположных результатов визуального отображения того же документа.

Реализация CSS (и особенно CSS2 ) в современных браузерах оставляет желать много лучшего. Наилучших результатов здесь добились авторы Gecko — движка для браузеров, на котором построены браузеры Netscape 6, Mozilla, Galeon и другие. Opera 6 тоже выглядит достаточно хорошо в плане поддержки стандартов CSS1 и CSS2 , Internet Explorer на фоне их выглядит довольно бледно — у него наблюдаются явные проблемы с реализацией некоторых частей спецификации CSS2 (что, впрочем, неудивительно — ребята из Редмонда всегда отличались оригинальным взглядом на вопрос поддержки в своих программах спецификаций, в разработке которых они же сами и принимали непосредственное участие).

И помимо всего этого у HTML есть еще один огромный недостаток — используя этот язык можно описать, как должен выглядеть документ, но нельзя описать то, какая информация содержится в этом документе. Это порождает целую массу проблем. Одной из самых серьезных можно назвать проблему поиска информации, потому что те же поисковые машины вынуждены лишь делать предположения о том, что документ, который они нашли в той или иной мере соответствует запросу. Но как ни хороши алгоритмы работы современных поисковых машин — в результатах их работы все равно много «мусора».

Язык XML появился на свет во многом благодаря существованию описанных выше проблем, когда стало ясно, что необходим язык, настолько же простой и понятный как HTML , но способный хранить в себе любую информацию в структурированном виде, имеющий синтаксис, который бы позволил легко писать программы для работы с документами XML , имеющий встроенные средства проверки корректности структуры и информации, описанной в документе и другие параметры, облегчающие создание, обработку и использование данных, описанных в документах XML . Нужно сказать, что к моменту создания XML подобный язык уже существовал (это язык SGML — Standard Generalized Markup Language ), но этот язык настолько сложен, что широкое использование его значительно затруднено. Надо сказать, что со своей задачей разработчики XML справились просто превосходно — спецификация языка XML 1.0 соответствует всем требованиям. Однако перейдем от слов к делу и посмотрим на пример XML -документа, например, описывающего книгу:

Как видите — содержимое этого документа говорит само за себя и даже человек, который впервые видит этот документ поймет что значат те или иные данные в нем. В этом и состоит основная прелесть XML — хорошо составленный XML документ содержит в себе информацию, которую одинаково легко сможет распознать как челоек, так и программа. При этом создать такой документ очень легко — спецификация XML никак не органичивает количество, структуру и имена тегов и аттрибутов, из которых состоит XML -документ. Фактически спецификация XML описывает лишь набор основных структур языка и соглашения об их синтаксисе. Все остальное вы свободны задать так, как вам необходимо. Кроме того спецификация XML позволяет вам самому разработать любой язык разметки, который нужен именно вам, и формально описать его структуру. Т.е. в принципе любой язык разметки текстовых документов может быть описан на языке XML (в том числе, кстати, и язык HTML ). Однако это отдельная очень большая тема и здесь мы ее рассматривать не будем.

Все сказанное выше было необходимо для того, чтобы вы поняли основную идею — с помощью XML вы можете описать любые данные в структурированном виде и затем легко обрабатывать эти данные, в том числе и на PHP , о чем и пойдет речь далее.

Способы обработки XML данных в PHP

В PHP существуют 2 модуля работы с XML , реализующие 2 разных стандарта обработки XML -данных: SAX ( Simple API for XML ) и DOM ( Document Object Model ). Необходимо вкратце пояснить, что представляют собой эти стандарты.

Стандарт SAX не является стандартом W3C , официальным сайтом для него является http://www.saxproject.org/. Этот стандарт описывает метод парсинга XML документов для получения данных из них. Т.е. этот метод обработки XML -документов позволит вам только прочитать данные из XML -документа и не более того. Создавать и изменять XML -документы с его помощью вы не сможете.

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

Другим стандартом для обработки XML -данных является DOM — стандарт W3C , спецификацию которого вы можете найти здесь. В отличие от SAX этот метод позволяет вам производить любые операции с XML -данными в очень удобной форме — представляя XML -документ как дерево объектов. Далее мы рассмотрим пример того, как можно работать с XML через DOM из PHP .

Чтение XML-данных в PHP с использованием SAX

Для того, чтобы показать, как использовать имеющиеся в PHP модули для работы с XML -данными возьмем реальный пример — колонка новостей, хранящаяся в XML файле.

Файл news.xml , в котором хранятся новости:

Файл test.php , выполняющий парсинг news.xml для получения новостей:

В результате работы файла test.php мы получим массив $news , содержащий все новости из файла news.xml . Если, к примеру сделать print_r($news) , чтобы посмотреть содержимое массива, то мы увидим примерно следующее:

Для того, чтобы потом вывести новости на странице, нам будет необходимо всего-лишь обработать элементы массива, например так:

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

Все эти недостатки делают область применения SAX достаточно ограниченной, тем более в условиях того, что существует другой, гораздо более мощный и удобный стандарт обработки XML -документов — DOM . О нем и пойдет речь в следующем разделе.

Обработка XML-данных в PHP с использованием DOM

Стандарт DOM обладает двумя основными достоинствами:

  1. Он не привязан к какой-то конкретной платформе или языку программирования. Используя DOM можно работать с XML -данными совершенно одинаково на C++, Java, JavaScript и т.д.
  2. Он позволяет выполять все операции по обработке XML -данных. Т.е. вы можете не только читать их, но и модифицировать содержимое XML -документа, вставляя туда новые теги, удаляя и изменяя их.

К сожалению в отношении PHP первое высказывание не относится т.к. единственная имеющаяся реализация интерфейса DOM для PHP не является таковой в полной мере, поскольку имеет совершенно другой интерфейс, что, конечно же не очень хорошо. Кроме того имеющийся интерфейс (по крайней мере пока) не поддерживает многие вещи, подчас являющиеся концептуальными для стандарта DOM . Но даже в таком виде этот интерфейс намного удобнее в использовании чем SAX и, я думаю, вы сами убедитесь в этом, посмотрев пару примеров, приведенных ниже:

Для начала попробуем реализовать ту же функцианальность, что и в примере, рассмотренном в предыдущем разделе (чтение колонки новостей из XML файла) но с использованием интерфейса DOM :

Как видите — код получился гораздо более простой и понятный. Кроме того он намного меньше зависит от структуры исходного XML файла и легче поддается модификации. Результат работы, естественно, тот же самый, что и для варианта с работй через SAX .

Однако и это не самый простой вариант обработки XML -документов, особенно для больших документов со сложной структурой. Основной проблемой в этом случае становится процесс доступа к данным, т.к. необходимо «вручную» пройти весь путь по XML -дереву до необходимых данных. К счастью из этой ситуации есть простой и элегантный выход и имя ему XPath . Это язык, также разработанный W3C и специально предназначенный для получения данных из деревьев DOM XML . Спецификация этого языка доступна здесь. К сожалению ввиду того, что имеющийся у нас XML -документ имеет очень простую структуру — я не могу продемонстрировать большинство интересных конструкций XPath на нем, но после прочтения спецификации вы поймете, что это очень мощный и удобный инструмент. Например выражение //category[@ > вернет вам имя продукта, расположенного под номером 3 в категории, имеющей >, причем положение самой node может быть произвольным внутри дерева XML . Здорово, не правда ли?

Посмотрим, как может выглядеть код предыдущего примера, если использовать XPath для получения всех node :

Как видите — с использованием XPath обработка XML стала еще проще. Но это еще не все. Как я уже говорил раньше — интерфейс DOM позволяет вам модифицировать дерево XML . Воспользуемся этим, чтобы добавить еще одну новость в XML -файл:

Java XML

J ava Development Kit поставляется с двумя парсерами XML: DOM и SAX, каждый из которых имеет свои сильные и слабые стороны. В этом руководстве мы рассмотрим несколько примеров создания, изменения и чтения XML файлов средствами библиотек DOM, SAX и JDOM.

Кроме этого, будут рассмотрены примеры использования библиотеки JAXB для преобразования Java объектов в XML файлы и обратно.

DOM XML парсер

DOM XML парсер — наиболее простой способ работы с XML файлами в Java. При работе с XML файлами производится разбор всего файла, строится его объектная модель, которая полностью загружается в память. Для каждого XML элемента создается свой объект, между которыми организуется удобный способ навигации. DOM XML парсер не рекомендуется использоваться при работе с XML файлами большого размера: с такими файлами работа происходит очень медленно и расходуется очень большое количество памяти.

  • Чтение XML файла средствами DOM XML
    Прочитать XML файл и распечатать каждый из его элементов.
  • Внесение изменений в XML файл средствами DOM XML
    Внесение изменений в существующий XML файл: изменить XML элемент, изменить значения атрибутов, добавить и удалить XML элемент.
  • Создание XML файла средствами DOM XML
    Создать новый XML файл, в котором определены новый документ, XML элементы и добавлены атрибуты.
  • Подсчет XML элементов в файле средствами DOM XML
    Отыскать все XML элементы в файле и подсчитать их количество.

SAX XML парсер


SAX XML парсер работает не так, как DOM: он не читает весь XML файл целиком, не загружает его в память и не создает объекты для каждого элемента. Вместо этого, SAX парсер использует функцию обратного вызова (callback function) org.xml.sax.helpers.DefaultHandler , с помощью которой информирует клиента об изменении структуры XML документа.

Техника работы станет более понятно после рассмотрения конкретных примеров использования SAX XML парсера.

  • Чтение XML файла средствами SAX XML
    Прочитать XML файл с помощью SAX функции обратного вызова.

JDOM XML парсер

Библиотека JDOM XML позволяет представить XML документ в простой и понятной форме, удобной для чтения и изменения данных. JDOM XML является полноценной альтернативой SAX и DOM.

  • Чтение XML файла средствами JDOM XML
    Прочитать XML файл с помощью JDOM и распечатать каждый из элементов.
  • Внесение изменений в существующий XML файл средствами JDOM XML
    Внесение изменений в существующий XML файл: изменить XML элемент, изменить значения атрибутов, добавить и удалить XML элемент.
  • Создание XML файла средствами JDOM XML
    Создать новый XML файл, в котором определены новый документ, XML элементы и добавлены атрибуты.

Использование JAXB аннотаций для преобразования Java объектов в XML и обратно.

Разбор большого XML файла с помощью PHP

В этой статье я покажу пример, как разобрать большой XML файл. Если на вашем сервере (хостинге) не запрещено увеличение времени работы скрипта, то можно разбирать XML файл весом хоть гигабайты, сам лично разбирал только файлы от озона весом 450 мегабайт.

При разборе больших XML файлов возникает две проблемы:
1. Не хватает памяти.
2. Не хватает выделенного времени для работы скрипта.

Вторую проблему с временем решить можно, если сервером это не запрещено.
А вот проблему с памятью решить сложно, даже если речь идет о своем сервере, то ворочать файлы по 500 мегабайт не очень просто а уж на хостинге и на VDS увеличить память просто не получится.

В PHP существует несколько встроенных вариантов обработки XML — SimpleXML, DOM, SAX.
Все эти варианты подробно описаны во многих статьях с примерами, но все примеры демонстрируют работу с полным XML документом.

Вот один из примеров, получаем объект из XML файла

Теперь можно обрабатывать этот объект, НО.
Как видно, весь XML файл считывается в память, затем все разбирается в объект.
То есть все данные попадают в память и если выделенной памяти мало, то скрипт останавливается.

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

Вот теоретический пример разбора большого XML файла.
Этот скрипт читает по одному символу из файла, собирает эти данные в блоки и отправляет в разборщик XML.
Такой подход полностью решает проблему с памятью и не вызывает нагрузки, но усугубляет проблему со временем. Как попытаться решить проблему со временем, читайте ниже.

function webi_xml ( $file )
<

$xml_parser = xml_parser_create ();
xml_parser_set_option ( $xml_parser , XML_OPTION_CASE_FOLDING , true );

// указываем какие функции будут работать при открытии и закрытии тегов
xml_set_element_handler ( $xml_parser , «startElement» , «endElement» );

// указываем функцию для работы с данными
xml_set_character_data_handler ( $xml_parser , «data» );

// открываем файл
$fp = fopen ( $file , «r» );

$perviy_vxod = 1 ; // флаг для проверки первого входа в файл
$data = «» ; // сюда собираем частями данные из файла и отправляем в разборщик xml

// цикл пока не найден конец файла
while (! feof ( $fp ) and $fp )
<

$simvol = fgetc ( $fp ); // читаем один символ из файла
$data .= $simvol ; // добавляем этот символ к данным для отправки

// если символ не завершающий тег, то вернемся к началу цикла и добавим еще один символ к данным, и так до тех пор, пока не будет найден закрывающий тег
if( $simvol != ‘>’ ) < continue;>
// если закрывающий тег был найден, теперь отправим эти собранные данные в обработку

// проверяем, если это первый вход в файл, то удалим все, что находится до тега if( $perviy_vxod )

// теперь кидаем данные в разборщик xml
if (! xml_parse ( $xml_parser , $data , feof ( $fp ))) <

// здесь можно обработать и получить ошибки на валидность.
// как только встретится ошибка, разбор прекращается
echo «
XML Error: » . xml_error_string ( xml_get_error_code ( $xml_parser ));
echo » at line » . xml_get_current_line_number ( $xml_parser );
break;
>

// после разбора скидываем собранные данные для следующего шага цикла.
$data = «» ;
>
fclose ( $fp );
xml_parser_free ( $xml_parser );

В этом примере я все сложил в одну функцию webi_xml() и в самом низу видно ее вызов.
Сам скрипт состоит из трех основных функций:
1. Функция которая ловит открытие тега startElement()
2. Функция которая ловит закрытие тега endElement()
3. И функция получения данных data() .

Предположим что содержимое файла 1.xml некий рецепт

= «1.0» encoding = «windows-1251» ?>
= «хлеб» preptime = «5» cooktime = «180» >
title > Простой хлеб title >
ingredient amount = «3» unit = «стакан» > Мука ingredient >
ingredient amount = «0.25» unit = «грамм» > Дрожжи ingredient >
ingredient amount = «1.5» unit = «стакан» > Тёплая вода ingredient >
ingredient amount = «1» unit = «чайная ложка» > Соль ingredient >
instructions >
step > Смешать все ингредиенты и тщательно замесить . step >
step > Закрыть тканью и оставить на один час в тёплом помещении . step >
step > Замесить ещё раз , положить на противень и поставить в духовку . step >
step > Посетить сайт webi.ru step >
instructions >
recipe >

Начинаем все с вызова общей функции webi_xml ( ‘1.xml’ );
Дальше в этой функции стартует разборщик и все имена тегов переводим в верхний регистр, чтобы все теги имели одинаковый регистр.

$xml_parser = xml_parser_create ();
xml_parser_set_option ( $xml_parser , XML_OPTION_CASE_FOLDING , true );

Теперь указываем какие функции будут работать для отлова открытия тега, закрытия и обработки данных

xml_set_element_handler ( $xml_parser , «startElement» , «endElement» );
xml_set_character_data_handler ( $xml_parser , «data» );

Дальше идет открытие указанного файла, перебор файла по одному символу и каждый символ добавляется в строковую переменную пока не будет найден символ >.
Если это самое первое обращение к файлу, то попутно будет удалено все что будет лишним в начале файла, все что стоит до
И отправит ее в разборщик
xml_parse ( $xml_parser , $data , feof ( $fp )) ;
После обработки данных строковая переменная сбрасыватеся и снова начинается сбор данных в строку и во второй раз сформируется строка

В третий

в четвертый
Простой хлеб


Обратите внимание, что строковая переменная всегда формируется по законченному тегу > и не обязательно посылать разбощику открытый и закрытый тег с данными например
Простой хлеб
Данному обработчику важно получить целый не разбитый тег, хоть один открытый, а в следущий шаг закрытый тег, или сразу получить 1000 строк файла, не важно, главное чтобы тег не разрывался, например
Простой хлеб
Так отправить данные обработчику нельзя, так как тег разорвался.
Вы можете придумать свою методику посылания данных в обработчик, например собирать по 1 мегабайту данных и отправлять в обработчик для повышения скорости, только следите чтобы теги всегда завершались, а данные можно разрывать
Простой
хлеб

Таким образом частями, как вы пожелаете можно отправить большой файл в обработчик.

Теперь рассмотрим каким образом эти данные обрабатываются и как их получить.

Начинаем с функции открывающих тегов startElement ( $parser , $name , $attrs )
Предположим, что обработка дошла до строки
ingredient amount = «3» unit = «стакан» > Мука ingredient >
Тогда внутри функции переменная $name будет равна ingredient то есть название открытого тега (до закрытия тега дело еще не дошло).
Так же в данном случае будет доступен массив атрибутов этого тега $attrs , в котором будут данные amount = «3» и unit = «стакан» .

После этого пошла обработка данных открытого тега функцией data ( $parser , $data )
В переменной $data будет все, что находится между открывающим и закрывающим тегом, в нашем случае это текст Мука

И завершается обработка нашей строки функцией endElement ( $parser , $name )
Это название закрытого тега, в нашем случае $name будет равна ingredient

А после этого опять пошло все по кругу.

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

function webi_xml ( $file )
<
global $webi_depth ; // счетчик, для отслеживания глубины вложенности
$webi_depth = 0 ;
global $webi_tag_open ; // будет содержать массив открытых в данный момент тегов
$webi_tag_open = array();
global $webi_data_temp ; // этот массив будет содержать данные одного тега

####################################################
### функция работы с данными
function data ( $parser , $data )
<
global $webi_depth ;
global $webi_tag_open ;
global $webi_data_temp ;
// добавляем данные в массив с указанием вложенности и открытого в данный момент тега
$webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ ‘data’ ].= $data ;
>
############################################

####################################################
### функция открывающих тегов
function startElement ( $parser , $name , $attrs )
<
global $webi_depth ;
global $webi_tag_open ;
global $webi_data_temp ;

// если уровень вложенности уже не нулевой, значит один тег уже открыт
// и данные из него уже в массиве, можно их обработать
if ( $webi_depth )
<
// здесь начинается обработка данных, например добаление в базу, сохранение в файл и т.д.
// $webi_tag_open содержит цепочку открытых тегов по уровню вложенности
// например $webi_tag_open[$webi_depth] содержит название открытого тега чья информация сейчас обрабатывается
// $webi_depth уровень вложенности тега
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]][‘attrs’] массив атрибутов тега
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]][‘data’] данные тега

print ‘данные ‘ . $webi_tag_open [ $webi_depth ]. ‘—‘ .( $webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ ‘data’ ]). ‘
‘ ;
print_r ( $webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ ‘attrs’ ]);
print ‘
‘ ;
print_r ( $webi_tag_open ); // массив открытых тегов
print ‘ ‘ ;

// после обработки данных удаляем их для освобождения памяти
unset( $GLOBALS [ ‘webi_data_temp’ ][ $webi_depth ]);
>

// теперь пошло открытие следующего тега и дальше обработка его произойдет на следующем шаге
$webi_depth ++; // увеличиваем вложенность

$webi_tag_open [ $webi_depth ]= $name ; // добавляем открытый тег в массив информаци
$webi_data_temp [ $webi_depth ][ $name ][ ‘attrs’ ]= $attrs ; // теперь добавляем атрибуты тега

#################################################
## функция закрывающих тегов
function endElement ( $parser , $name ) <
global $webi_depth ;
global $webi_tag_open ;
global $webi_data_temp ;

// здесь начинается обработка данных, например добаление в базу, сохранение в файл и т.д.
// $webi_tag_open содержит цепочку открытых тегов по уровню вложенности
// например $webi_tag_open[$webi_depth] содержит название открытого тега чья информация сейчас обрабатывается
// $webi_depth уровень вложенности тега
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]][‘attrs’] массив атрибутов тега
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]][‘data’] данные тега

print ‘данные ‘ . $webi_tag_open [ $webi_depth ]. ‘—‘ .( $webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ ‘data’ ]). ‘
‘ ;
print_r ( $webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ ‘attrs’ ]);
print ‘
‘ ;
print_r ( $webi_tag_open );
print ‘ ‘ ;

unset( $GLOBALS [ ‘webi_data_temp’ ]); // после обработки данных удаляем массив с данными целиком, так как произошло закрытие тега
unset( $GLOBALS [ ‘webi_tag_open’ ][ $webi_depth ]); // удаляем информацию об этом открытом теге. так как он закрылся

$xml_parser = xml_parser_create ();
xml_parser_set_option ( $xml_parser , XML_OPTION_CASE_FOLDING , true );

// указываем какие функции будут работать при открытии и закрытии тегов
xml_set_element_handler ( $xml_parser , «startElement» , «endElement» );

// указываем функцию для работы с данными
xml_set_character_data_handler ( $xml_parser , «data» );

// открываем файл
$fp = fopen ( $file , «r» );

$perviy_vxod = 1 ; // флаг для проверки первого входа в файл
$data = «» ; // сюда собираем частями данные из файла и отправляем в разборщик xml

// цикл пока не найден конец файла
while (! feof ( $fp ) and $fp )
<
$simvol = fgetc ( $fp ); // читаем один символ из файла
$data .= $simvol ; // добавляем этот символ к данным для отправки

// если символ не завершающий тег, то вернемся к началу цикла и добавим еще один символ к данным, и так до тех пор, пока не будет найден закрывающий тег
if( $simvol != ‘>’ ) < continue;>
// если закрывающий тег был найден, теперь отправим эти собранные данные в обработку

// проверяем, если это первый вход в файл, то удалим все, что находится до тега if( $perviy_vxod )

// теперь кидаем данные в разборщик xml
if (! xml_parse ( $xml_parser , $data , feof ( $fp ))) <

// здесь можно обработать и получить ошибки на валидность.
// как только встретится ошибка, разбор прекращается
echo «
XML Error: » . xml_error_string ( xml_get_error_code ( $xml_parser ));
echo » at line » . xml_get_current_line_number ( $xml_parser );
break;
>

// после разбора скидываем собранные данные для следующего шага цикла.
$data = «» ;
>
fclose ( $fp );
xml_parser_free ( $xml_parser );
// удаление глобальных переменных
unset( $GLOBALS [ ‘webi_depth’ ]);
unset( $GLOBALS [ ‘webi_tag_open’ ]);
unset( $GLOBALS [ ‘webi_data_temp’ ]);

Весь пример сопроводил комментариями, теперь тестируйте и экспериментируйте.
Обратите внимание, в функции работы с данными в массив данные не просто вставляются, а именно добавляются с помощью «.=» так как данные могут поступать не в целом виде и если сделать просто присвоение, то время от времени вы будете получать данные кусками.

Ну вот и все, теперь при обработке файла любого размера памяти хватит, а вот время работы скрипта увеличить можно несколькими способами.
В начало скрипта вставьте функцию
set_time_limit ( 6000 );
или
ini_set ( «max_execution_time» , «6000» );

Либо добавьте в файл .htaccess текст
php_value max_execution_time 6000

Данные примеры увеличат время работы скрипта до 6000 секунд.
Увеличить время подобным образом можно только в выключенном безопасном режиме.

Если у вас есть доступ к редактированию php.ini можете увеличить время с помощью
max_execution_time = 6000

Например на хостинге мастерхост на момент написания статьи увеличение времени скрипта запрещено, не смотря на выключенный безопасный режим, но если вы профи, вы можете сделать свою сборку php на мастерхосте, но об этом не в этой статье.

Комментарии

13.11.2009 developer
проверил.
взял файл озона 450 мб с книгами.
и обработал его этим примером.
вставлял в базу данные минут 30, долго, но в итоге вставил.

28.02.2010 leksus.info
у меня хмл-файл на 25 гигов, вот думаю, сколько это времени займёт :)
Я так понимаю, если указать считываемые кусочки по 1мб, дело пойдёт быстрее?

01.03.2010 Админ
25 гигов это конечно круто.
если честно, не знаю что тут может ускорить процесс, надо экспериментировать.
разобрать конечно можно такой файл, но сколько часов это будет обрабатываться.

01.05.2010 Alex-Dnepr
PHP для разбора больших баз не очень-то подходит, причем — всего лишь в силу того, что сам процесс занимает очень много времени (450MB = 30мин. = 1800сек.), а, очень часто, настройки веб-сервера просто не позволяют его осуществить полностью из-за установленного лимита времени на работу php-скрипта (например стандартные для Апача 30сек.).
Такие вещи реально осуществлять на своем выделенном сервере (виртуальном либо реальном), так как появляется возможность изменения данного лимита времени исходя из своих потребностей.
Поэтому, в этом плане, парсер на базе perl — один из лучших вариантов.

P.S. Пробовал изменять размер куска на считывание — почти нулевое изменение производительности.


01.05.2010 админ
Alex-Dnepr, конечно, для подобных вещей perl более предпочтителен.
Скорость выполнение подобного разбора в perl должна быть быстрее, но не сильно уж быстрее.
Да и потом у perl по времени тоже существуют ограничения, такие же как в php.

02.05.2010 Alex-Dnepr
Как ни крути, но sax-парсер — медленный.
Для ускорения разбора больших баз можно попробовать использовать парсер, построенный, например на базе strpos() и substr().

02.05.2010 админ
Alex-Dnepr, на базе strpos() и substr() тоже можно, но будет ли быстрее. мне кажется, что не будет быстрее.
проверки и поиск символов по тексту создаст тоже не малую нагрузку.
Но это все уже тестировать надо.
Если прирост в скорости будет значительный, тогда наверное стоит обратить внимание на обработку строковыми функциями.

10.05.2010 Alex-Dnepr
Здравствйте, Admin.

Какая средняя скорость разбора больших XML файлов sax-парсером была зафиксирована Вами (размер файла/время обработки)?

11.05.2010 админ
Да вот тут я не отвечу. Я не проводил тестов на время.
Была задача сделать разбор файлов до 50 МБ на хостинге.
Естественно обычным способом разобрать не получалось, не хватало памяти.
А вот вариант описанный в этой статье подошел и укладывался в ресурсы хостинга, хватало и памяти и времени.
А вот сколько по времени длились разборы, я вот тут не засекал.

14.05.2010 Alex-Dnepr
Попробовал парсить XML-базу с помощью строковых функций — результат достаточно преемлемый.
По факту, разбор XML базы размером 500 Мб (только чтение — без записи в БД) с помощью SAX занял 460 сек, а строковыми функциями — 260 сек.

14.05.2010 админ
результат конечно впечатляет, почти в два раза быстрее.
но все ли вы учли? например разбор атрибутов предусмотрели?
может покажите этот пример(на почту), я его обработаю, потестирую и присоединю к этой статье.

15.05.2010 Alex-Dnepr
Как уже указывал — такие результаты были достигнуты в режиме чтения XML-базы — без учета затрат времени на работу с СУБД (например MySQL).

По факту, необходимость записи в базу данных — практически нивелирует относительную разницу в результатах работы парсеров.

П.С. Выделение атрибутов осуществляется и не ничем не отличается от процесса выделения значений, заключенных в теги.
По факту — это тот же sax, разница в том, что выделение тегов и атрибутов осуществляется с помощью строковых функций.

15.05.2010 админ
Про атрибуты я упомянул потому, что выделение атрибутов такое же затратное действие как и выделение значений тегов. И если опустить атрибуты, то скорость увеличится, поэтому я и спросил про атрибуты.
А зачем учитывать время работы с базой?
Тут было интересно узнать скорость самого разбора. Раз он быстрее в два раза, значит более предпочтителен.
Ведь может понадобиться не вставлять данные в базу, а лишь найти несколько значений в большом XML

26.07.2010 Виталий
А можно после считывания из xml сразу удалять строку?
т.е. считал, закинул эти данные в базу(например), удалил эту строку и так далее. а то у меня строк 400 считывает и потом 504ю ошибку выдает, приходится удалять уже добавленные строки.

27.07.2010 Никита
Виталий, просто так удалить строку из файла нельзя.
Для этого надо прочитать все оставшиеся строки и записать их в новый файл.

28.07.2010 Виталий
А если крупный файл, то оперативку сильно забивать будет.

28.07.2010 Никита
Виталий, ну у тебя же проблема с какой-то ошибкой после прочтения 400 строк.
Скорее всего просто не хватает времени.
А для того, чтобы выкинуть обработанные строки из файла, нужно оставшиеся строки читать и складывать в новый файл и тут опять же возникнет твоя ошибка.
Если прочитать всю оставшуюся часть файла и сохранить в новый файл, то тут конечно не хватит оперативки, если файл большой.

30.07.2010 Виталий
В общем ничего сочинять не нужно. надо просто запускать такие вещи через крон, и все потихоньку за раз хоть за час хоть за два добавится.

01.04.2011 m11
А можно пример как в базу вставить полученные данные?

12.04.2011 Алексей
Может быть что-то изменилось в PHP’шном парсере. Но факт тот, что сейчас, судя по всему, пляски с поиском начала и конца тегов не нужны.

Читай хоть по одному символу — оно запоминает и парсит как надо:

while ($data = fread($fp, 1)) <
if (!xml_parse($xml_parser, $data, feof($fp))) <
* * * *
>
>

Как сделать xml parser на PHP

Я видел много xml parser`ов, но не затрагивал при этом веб-программирование. Теперь же я хочу выяснить и научиться вместе с вами, как сделать простой xml parser в php.

Не, ну на самом деле: xml-файлы — очень полезная штука. И любой профессионал должен… нет, не должен, а обязан знать, как с ними работать. Мы же хотим стать профессионалами? Если Вы на моем блоге, то такое желание у Вас есть.

Мы предполагаем, что знаем, что такое XML и описывать его здесь не будем. Ну, если не знаем, то легко узнаем здесь: http://ru.wikipedia.org/wiki/XML

При поиске способов парсинга XML на PHP, я обнаружил простой набор функций в PHP для работы с XML-файлами, который называется «XML Parser Functions». Парсинг начинается с инициализации парсера вызовом функции xml_parser_create:

Потом нам нужно сказать парсеру, какие функции будут обрабатывать попадающиеся ему xml-теги и текстовую информацию в процессе парсинга. Т.е. нужно установить некие обработчики:

Эта функция отвечает за установку обработчиков начала элемента и конца элемента. Например, если в тексте xml-файла встретится комбинация , то функция startElement сработает, когда парсер найдет элемент , а функция endElement — при нахождении .

Сами же функции startElement и endElement принимают несколько параметров согласно документации по php:

А как же считывать данные из файла? Мы же пока не видели ни одного параметра для этого ни в одной из функций! А об этом дальше: считывание файла возлагается на плечи программиста, т.е. мы должны использовать стандартные функции для работы с файлами:

Открыли файл. А теперь нужно построчно считывать его и скармливать считываемые строки функции xml_parse:

Здесь заметим две очень важные вещи. Первая — это то, что функции xml_parse в третьем параметре нужно передать флаг считывания последней строки (true — если строка последняя, false — если нет). Второе — это то, что как и в любом деле, мы должны следить здесь за ошибками. За это отвечают функции xml_get_error_code и xml_error_string. Первая функция получает код ошибки, а вторая — по полученному коду возвращает текстовое описание ошибки. Что в результате возникновения ошибки получится — рассмотрим позже. Не менее полезная функция xml_get_current_line_number скажет нам номер текущей обрабатываемой строки в файле.

И как всегда мы должны освободить занимаемые системой ресурсы. Для парсинга XML — это функция xml_parser_free:

Вот, основные функции мы рассмотрели. Пора бы посмотреть их на деле. Для этого я придумал xml-файл с очень простой структурой:

Назовем этот файл data.xml и попытаемся его распарсить с помощью следующего кода:

В результате разработанного нами простейшего скрипта браузер вывел в свое окно следующую информацию:

Попробуем испортить XML-файл, заменив тег

на , а закрывающий тег оставив прежним:

XML Error: Mismatched tag at line 5

Ух ты! Сообщения об ошибках работают! Причем довольно информативные.

Эх, я забыл еще одну вещь… Мы же не вывели текст, содержащийся внутри тегов address и phone. Исправляем наш недочет — добавляем текстовый обработчик с помощью функции xml_set_character_data_handler:

И добавляем в код саму функцию-обработчик:

Посмотрим теперь на вывод:


О! Теперь вывели все!

Кстати, кто-нибудь заметил, что имена тегов и атрибутов все большими буквами написаны? Странно… они же в нашем xml-файле малыми буквами обозначены. Видимо где-то какие-то настройки установлены, чтобы делать uppercase…

Ааа, нашел! Оказывается есть еще функция xml_parser_set_option:

Таким вызовом мы отменяем вывод имен атрибутов и имен тегов большими буквами:

В этой статье мы рассмотрели самый простой, но для большинства задач достаточный метод вытаскивания информации из XML-файлов. Я еще слышал про какие-то другие более мощные методы, но их буду рассматривать, когда сам изучу немного

Часть 2. Расширенные методы парсинга XML

Методы синтаксического анализа объемных или сложных XML-документов в PHP5

Серия контента:

Этот контент является частью # из серии # статей: XML для PHP-разработчиков

Этот контент является частью серии: XML для PHP-разработчиков

Следите за выходом новых статей этой серии.

В PHP5 увеличено разнообразие методов синтаксического анализа (парсинга) XML. Парсер Expat SAX Джеймса Кларка, который теперь основан на библиотеке libxml2, больше не является единственным полнофункциональным парсером. Нам уже знакома возможность парсинга посредством DOM в полном согласии со стандартом W3C. Дополнительные возможности предлагает SimpleXML, который мы рассмотрели в части 1 (см. Ресурсы), и XMLReader, который проще в понимании и быстрее в работе, чем SAX. Все расширения XML теперь основаны на библиотеке libxml2 проекта GNOME. Эта унифицированная библиотека позволяет разным расширениям взаимодействовать друг с другом. В настоящей статье обсуждаются методы парсинга XML в РНР5 с акцентом на объемные или сложные XML-документы. В ней рассказывается о методах парсинга и о критериях выбора, когда он есть, оптимального метода для синтаксического анализа XML-документов разного типа.

SimpleXML

Другие статьи этой серии

В первой статье этой серии содержится важная информация об XML и инструкции по началу работы с интерфейсами прикладных программ (API). В ней демонстрировалось, что SimpleXML в сочетании с Document Object Model (DOM) служит идеальным инструментом для разработчиков, имеющих дело с простыми, предсказуемыми и относительно компактными XML-документами.

XML и PHP5

Язык Extensible Markup Language (XML) можно назвать и языком разметки, и форматом хранения текстовых данных; он предоставляет текстовые средства для описания древовидных структур и их применения к информации.

В РНР5 имеются как новые, так и переписанные расширения для XML-парсинга. SimpleXML, DOM и процессор XSLT загружают в память весь XML-документ целиком. Simple API for XML (SAX) и XMLReader относятся к тем парсерам, которые обрабатывают XML-документ по частям. SAX функционирует так же, как в РНР4, но теперь он основан на библиотеке libxml2, а не expat. Тем, кто знаком с DOM по другим языкам, в РНР5 будет легче с ним работать, чем в предыдущих версиях РНР.

Основы XML-парсинга

Существует два основных способа XML-парсинга: на базе деревьев и на базе потоков. Метод дерева предусматривает загрузку в память всего XML-документа целиком. Древовидная структура файла позволяет произвольно обращаться к элементам документа и редактировать XML. Примерами парсеров по методу дерева служат DOM и SimpleXML. Они хранят древовидную структуру в памяти в разных, но взаимодействующих форматах. При поточном парсинге весь документ в память не загружается. В данном случае термин «поток» употребляется в том же смысле, что и при описании поточного аудио. Происходит то же самое и по тем же причинам: данные поступают мелкими порциями с целью экономии полосы пропускания и ресурсов памяти. При поточном парсинге доступен только тот узел, который анализируется в данный момент, а редактирование XML-документа целиком невозможно. Примерами поточных парсеров служат XMLReader и SAX.

Парсеры, работающие по методу дерева

Парсеры, работающие по методу дерева, загружают в память весь документ, так что корень напоминает ствол дерева, а все дочерние, внучатые и более отдаленные потомки и атрибуты служат ветвями. Самый известый парсер, работающий по методу дерева, это DOM. Самый простой — SimpleXML. Рассмотрим тот и другой.

Парсинг при помощи DOM

Стандарт DOM, согласно W3C, представляет собой «. не зависящий от платформы и языка программирования интерфейс, который позволяет программам и сценариям динамически обращаться к документам и редактировать их содержание, структуру и стиль». Библиотека libxml2 проекта GNOME реализует DOM вместе со всеми его методами на языке С. Так как все XML-расширения РНР5 основаны на libxml2, они поддерживают полное взаимодействие друг с другом. Это взаимодействие значительно улучшает их функциональность. Например, можно извлечь элемент при помощи поточного парсера XMLReader, импортировать его в DOM и извлечь данные с использованием XPath. Подтверждение подобной гибкости продемонстрировано листинге 5.

Парсер DOM работает по методу дерева. Он прост для понимания и применения, так как его структура в памяти напоминает оригинальный XML-документ. DOM передает информацию приложению, создавая дерево объектов, в точности повторяющее дерево элементов из XML-файла, так что каждый элемент XML служит узлом этого дерева. DOM – это стандарт W3C, что принесло ему признание разработчиков ввиду его согласованности с другими языками программирования. Так как DOM строит дерево всего документа, он потребляет большой объем памяти и много ресурсов процессора.

DOM в действии

Если ввиду какого-то ограничения вы вынуждены выбрать единственный парсер, имеет смысл выбрать DOM хотя бы в силу его гибкости. DOM позволяет составлять XML-документы, модифицировать их, обращаться к ним, проверять и преобразовывать их. При этом можно использовать все методы и свойства DOM.Большинство методов DOM второго уровня реализованы с надлежащей поддержкой свойств. Благодаря чрезвычайной гибкости DOM анализируемые документы могут быть чрезвычайно сложными. Однако помните, что за гибкость приходится платить тем, что весь документ загружается в память целиком.

В примере, приведенном в листинге 1, DOM применяется для парсинга документа и извлечения элемента при помощи функции getElementById . Перед ссылкой на идентификатор документ необходимо проверить, установив val >. Согласно стандарту DOM, для этого требуется DTD, который определяет атрибут ID как тип ID.

Листинг 1. Использование DOM с простым документом

Функция getElementsByTagName() возвращает новый экземпляр класса DOMNodeList , содержащий элементы с заданным именем тега. Конечно, нужно пролистать список. Изменение структуры документа во время работы со списком NodeList , выданным функцией getElementsByTagName() , влияет на список NodeList , с которым вы работаете (см. листинг 2). Проверка в данном случае не требуется.

Листинг 2. Метод DOM getElementsByTagName

В примере из листинга 3 DOM используется с XPath.

Листинг 3. Использование DOM и парсинг с применением XPath

Высказав все эти приятные вещи по поводу DOM, я хочу привести пример того, что не надо делать с DOM, а затем, в следующем примере, показать, как это обойти. Листинг 4 иллюстрирует загрузку объемного файла в DOM только с целью извлечения данных из одного атрибута при помощи DomXpath.

Листинг 4. Неправильное использование DOM с XPath при работе с объемным XML-документом

В последнем примере (листинг 5) DOM с XPath применяется точно так же, только данные передаются в XMLReader по одному элементу за раз с использованием метода expand() . При этом узел, переданный XMLReader , преобразуется в DOMElement .

Листинг 5. Правильное использование DOM с XPath при работе с объемным XML-документом

Парсинг при помощи SimpleXML

Расширение SimpleXML – еще один способ парсинга XML-документа. Для расширения SimpleXML требуется PHP5 и используется встроенная поддержка XPath. SimpleXML лучше всего работает с несложными данными XML. В том случае, если XML-документ не слишком сложен, глубок и не имеет смешанного контента, SimpleXML проще в применении, чем DOM, как и предполагает его название. Он интуитивно понятен, если вы работаете с известной структурой документа.

SimpleXML в действии

SimpleXML обладает многими преимуществами DOM и проще в программировании. Он позволяет легко обращаться к дереву XML, имеет встроенную поддержку проверки и XPath, а также взаимодействует с DOM, обеспечивая ему поддержку при чтении и записи XML-документов. Документы, анализируемые SimpleXML, пишутся легко и быстро. Однако помните, что, как и в случае DOM, простота и гибкость SimpleXML достигается ценой загрузки в память всего XML-документа целиком.

Код, приведенный в листинге 6, извлекает из примера XML-документа сюжет произведения, содержащийся в элементе

Листинг 6. Извлечение фрагмента текста


С другой стороны, может понадобиться извлечь многострочный адрес. Когда у одного родительского элемента имеется несколько экземпляров дочернего элемента, применяется обычная методика итерирования. Эта функциональность демонстрируется в листинге 7.

Листинг 7. Извлечение нескольких экземпляров элемента

Кроме чтения имен элементов и их значений, SimpleXML может обращаться к атрибутам элемента. В листинге 8 производится обращение к атрибутам элемента; это делается точно так же, как обращение к элементам массива.

Листинг 8. Демонстрация обращения SimpleXML к атрибутам элемента

В последнем примере (см. листинг 9) SimpleXML и DOM используются с расширением XMLReader . При помощи XMLReader данные передаются последовательно, по одному элементу, с использованием метода expand() . Этим методом узел, переданный XMLReader , можно преобразовать в DOMElement , а затем передать SimpleXML.

Листинг 9. Использование SimpleXML и DOM с расширением XMLReader для анализа объемного XML-документа

Потоковые парсеры

Потоковые парсеры называются так потому, что они анализируют XML в потоке, во многом напоминая работу потокового аудио. В каждый момент времени они работают с одним отдельным узлом, а закончив, совершенно забывают о его существовании. XMLReader — это pull-парсер, и программирование для него во многом напоминает извлечение результата запроса к таблице базы данных при помощи курсора. Это облегчает работу с незнакомыми или непредсказуемыми XML-файлами.

Парсинг при помощи XMLReader

XMLReader — это потоковый парсер того типа, который часто называют курсорным или pull-парсером. XMLReader вытягивает информацию из XML-документа по требованию. Он основан на API, полученном из C# XmlTextReader. В PHP 5.1 он включен и задействован по умолчанию и основан на библиотеке libxml2. До выхода PHP 5.1 расширение XMLReader не было включено по умолчанию, но было доступно в PECL (см. Ресурсы). XMLReader поддерживает пространства имен и проверку, включая DTD и Relaxed NG.

XMLReader в действии

Как потоковый парсер, XMLReader хорошо подходит для работы с объемными XML-документами; программировать в нем намного легче и обычно быстрее, чем в SAX. Это лучший потоковый парсер.

В следующем примере (листинг 10) объемный XML-документ анализируется при помощи XMLReader.

Листинг 10. XMLReader с объемным XML-файлом

Парсинг при помощи SAX

Simple API for XML (SAX) представляет собой потоковый парсер. События связаны с читаемым XML-документом, поэтому SAX программируется в стиле обратных вызовов. Существуют события для открывающих и закрывающих тегов элемента, сущностей и ошибок парсинга. Главная причина использования парсера SAX вместо XMLReader заключается в том, что парсер SAX иногда более эффективен и обычно лучше знаком. Важный недостаток — код для парсера SAX получается сложнее, и его труднее писать, чем для XMLReader.

SAX в действии

SAX должен быть знаком тем, кто работал с XML в PHP4, а расширение SAX в PHP5 совместимо с версией, к которой они привыкли. Так как это потоковый парсер, он хорошо справляется с объемными файлами, но это не лучший выбор, чем XMLReader.

В листинге 11 приведен пример обработки объемного XML-документа парсером SAX.

Листинг 11. Использование SAX для анализа объемного XML-файла

Заключение

PHP5 предлагает большое разнообразие методов парсинга. Парсинг при помощи DOM, который теперь полностью совместим со стандартом W3C, — знакомый вариант, подходящий для сложных, но относительно компактных документов. SimpleXML — это способ работы с простыми и не слишком объемными документами, а потоковый парсер XMLReader, который легче и быстрее, чем SAX, предпочтителен для очень больших документов.

Ресурсы для скачивания

Похожие темы

  • Оригинал статьи (EN).
  • XML для PHP-разработчиков, часть 1: Работа с XML в PHPза 15 минут (Клифф Морган, developerWorks, февраль 2007 г.): В первой статье этой серии из трех частей рассказывается о реализации XML в РНР5 и о том, как легко работать с XML в среде РНР.
  • XML для PHP-разработчиков, часть 3: дополнительные методы чтения, организации и составления XML-документов (Клифф Морган, developerWorks, март 2007 г.): в заключительной части серии из трех статей об XML для РНР-разработчиков рассказывается о методах чтения, обработки и составления XML-документов в РНР5.(EN)
  • SAX, the power API (Benoît Marchal, developerWorks, август 2001 г.): Введение в SAX, сравнение DOM и SAX, инструкции по работе с SAX (EN).
  • Reading and writing the XML DOM in PHP (Jack Herrington, developerWorks, декабрь 2005 г.): Три метода чтения XML: библиотека DOM, синтаксический анализатор SAX и регулярные выражения. Также рассказывается, как писать XML с применением текстовых шаблонов DOM и PHP (EN).
  • What kind of language is XSLT (Michael Kay, developerWorks, апрель 2005 г.): Об истоках языка XSLT и его преимуществах (EN).
  • Tip: Implement XMLReader: An interface for XML converters (Benoît Marchal, developerWorks, ноябрь 2003 г.): В этой статье исследуются API для конвейеров XML и причины, по которым знакомый интерфейс XMLReader подходит для многих компонентов. (EN)
  • SimpleXML Processing with PHP (Elliotte Rusty Harold, developerWorks, октябрь 2006 г.): Расширение SimpleXML позволяет PHP-страницам обращаться к XML с запросами, вести в них поиск, модифицировать и повторно публиковать его (EN).
  • A PHP5 migration gu >

Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

XML парсер с функцией автозамены ключей на значения из шаблона GoogleDocs

Решение, разработанное на основании Google Sheets и Google Docs с использованием скриптов на Google Apps Script, создано для распарсивания XML файла (получение из него пар ключ-значение) и дальнейшего формирования документа в Google Docs с измпользованием полученных данных и шаблона.

Алгоритм действия файла очень прост. Вот так выглядит лист управления:

Алгоритм работы очень прост:

  1. Сначала загружаем файлы XML на Google Диск.
  2. Нажимаем кнопку 1(обновить) – подтянется список всех XML на вашем Google Диске.
  3. Из выпадающего списка (треугольник справа от названия) выбираем свой XML файл.
  4. Нажимаете кнопку 2(спарсить данные с выбранного XML файла) – XML распарсится в нужный вид (список будет на вкладке test). Когда скрипт окончит свою работу, Вы в правом нижнем углу документа увидите сообщение, что все сделано.
  5. После этого вводите полный адрес своего Google Doc-шаблона, в котором нужно поменять ключи на значения (Можно скопировать со строки браузера).
  6. Нажимаем на кнопку 3(создать копию шаблона и заменить ключи на значения) – создается копия Вашего шаблона в папке на Google Диске – «Готовые файлы» (если таковой нет – скрипт ее создаст). Имя файла точно такое же как и имя XML.


Так же, если нет необходимости контроллировать весь процесс поэтапно, можно запустить скрипт по пунктам 3-6 одной кнопкой.
Эти 3 кнопки продублированы сверху в Меню – для удобства пользования.

Вторая вкладка — это вкладка dop. Здесь находятся дополнительные ключи, введенные вручную, которые так же будут учавствовать в преобразовании шаблона в готовый файл.

Распарсенные данные с XML файла заносятся во вкладку test. Так же там имеются 2 дополнительные кнопки для замены кода региона на его название и для замены кода ВЕД на его наименование (информация берется со скрытых листов в этом же документе).

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

Функции разборщика xml

Приведу примеры выгрузки и загрузки многоуровневого (с группами) справочника номенклатуры. Примеры подробно комментированы, и в конце статьи есть ссылка на работающую конфигурацию для 1С:Предприятие 7.7.

Почему не 8.0? Потому что в 8.0 похожий XML-парсер уже есть. Вы найдете почти полное сходство между этим последовательным парсером XML (видимо, заимствованным из .NET, класс XmlTextReader и XmlTextWriter) и приведенными ниже библиотечными функциями (вы можете вынести их, например, в глобальный модуль, снабдив ключевым словом Экспорт, а можете этого не делать).

Почему я избегаю использовать штатные средства 1С 7.7? Потому что они потребляют память примерно 10-кратно по сравнению с объемом исходного файла XML. Это значит, что по мере роста файла XML будут расти «тормоза», вплоть до момента, когда память не будет исчерпана полностью (либо приведет к ситуации, когда загрузка уйдет «в своп»). Модель DOM (которую применяет 1С:Предприятие 7.7) расчитана на обработку небольших документов XML, которые должны располагаться в памяти целиком.

Конечно, внешней компонентой делать то же самое намного аккуратнее, и соблюдается принцип объектной ориентированности. Пример компоненты, сделанной средствами .NET приведен в этой статье:
Книга знаний: Написание внешних компонент для 1С на VB.NET и C#

Внешняя компонента для 1С, которая не требует наличия среды исполнения .NET:
http://x-romix.narod.ru/OpenXML.rar

Однако, если внешние компоненты по каким-то причинам неприменимы (постоянно сталкиваюсь со страхом перед внешними компонентами, который я назвал бы, с известной долей шутки, «компонентофобия»), то примерно то же самое делает и приведенный ниже программный код на языке 1С.

Кроме того, модель DOM намного сложнее (по сравнению, например, с файлами DBF) — поэтому приходится сталкиваться еще и с XML-фобией: для обмена применяют все, что угодно, но не XML. Но это удобный, консервативный — происходит от древнего языка разметки SGML — и простой по своей сути формат (намного удобнее и приятнее DBF) — «тормоза» и непрактичность (в случае потоковой выгрузки) ему придает именно модель DOM. Всякому инструменту — свое применение, и вряд ли стоит применять объектную модель там, где подойдет простое последовательное чтение или запись текстового файла.

Имена функций я сделал такие же, как в 1С:Предприятие 8.0. Я предполагаю, что мало кто страдает «восьмеркофобией», и не сможет понять способ парсинга (разбора) текстовых файлов XML (на примере справочника товаров). Тем более, что парсер занимает меньше строк кода, чем можно было бы предположить: фактически, он предельно прост.

Это был пример обработки, которая читает файл XML, и создает многоуровневый справочник товаров.
А теперь приведу пример записи того же самого файла XML.

Как видим, весь алгоритм записи файла XML занимает 100 строк, а весь алгоритм чтения (парсинга) XML — 116 строк (учитывая комментарии и пустые строчки, которые я добавил в код для ясности).

Чтение и запись XML в этом примере происходит намного быстрее, и не потребляет память, по сравнению с тем, как это делает парсер DOM (от которого, напомню, фирма 1С отказалась в версии 1С:Предприятие 8.0, применив более простые средства последовательного доступа к XML). Имена библиотечных функций, приведенных выше, я сделал такими же, как в 8-ке. Удалось даже, на мой взгляд, несколько улучшить алгоритм. А именно, методы для чтения элемента и для записи завершающего элемента принимают «контрольные» параметры — ожидаемый тег или список ожидаемых тегов.

Это, на мой взгляд, помогает сделать код яснее.

Ссылка на файл с работающим примером конфигурации для 1С 7.7:
http://x-romix.narod.ru/XML_doc.rar
(скачивать левой кнопкой мыши, 288К)

От Гения 1С:
Друзья, если сделать обработку, назвать ее счажем ОбработкаXML, то также будет соблюдаться принцип объектно-ориентированности. И не нужно будет вызывать функции с префиксом xml_. Достаточно будет написать:

Функции разборщика xml

Вступайте в мою группу помощник программиста.
В ней мы обсуждаем программирование в 1С.

Чтение и запись XML в языке 1С 8.3, 8.2 (в примерах)

С уважением, Владимир Милькин (преподаватель школы 1С программистов и разработчик обновлятора).

Подписывайтесь и получайте новые статьи и обработки на почту (не чаще 1 раза в неделю).

Вступайте в мою группу ВКонтакте, Одноклассниках, Facebook или Google+ — самые последние обработки, исправления ошибок в 1С, всё выкладываю там в первую очередь.

Как помочь сайту: расскажите (кнопки поделиться ниже) о нём своим друзьям и коллегам. Сделайте это один раз и вы внесете существенный вклад в развитие сайта. На сайте нет рекламы, но чем больше людей им пользуются, тем больше сил у меня для его поддержки.

Нажмите одну из кнопок, чтобы поделиться:

Функции разборщика xml

Я поначалу совсем не хотел останавливаться на том, что такое XML, но все-таки несколько слов сказать придется, чтобы те, кто про него услышали первый раз, прочитав эти строки, были в курсе основных идей.
По сути XML представляет собой обычный текст, который разделяется на логические группы с помощью специальных меток, которые называют “тэг”.
Тэг представляет собой слово, которое заключено в угловые скобки — например вот так:

Для того, чтобы начать группу вы указывает просто слово в скобках — еще раз повторим
Для окончание группы вы указываете такой же тэг, но слово предваряется символом “/”. Вот так:

В итоге группа внутри тэга test выглядит вот так:
Группа символов для тестирования

Тэги могу вкладываться один в другой — например вот так:

Группа символов для тестирования 01
Группа символов для тестирования 02
Группа символов для тестирования 03

Кроме вложений текста в тэгах можно указывать атрибуты — вот так:

Группа символов для тестирования 01

Назначение тэгов очень простое — надо отметить/выделить/сгруппировать какую-то информацию для того, чтобы потом ее можно было использовать. Это может быть список имен, список книг, список фирм, список вакансий и т.д.
Например, я хочу написать список контактов, с указанием имени, фамилии и e-mail. Можно сделать это так (но можно и по-другому — здесь все зависит от вашей фантазии и требований задачи):

Василий
Курочкин
vas@pisem.net

Георгий
Папанов
geogr@gmail.com

Семен
Баринов
barinov@yandex.ru

Не ищите тайного смысла — я просто сделал строку, в которой выделил нужные мне части — контакт (тэг contact) и внутри определил имя, фамилию и e-mail (тэги firstName, lastName, email). Также с помощью атрибута type я определи тип контакта — друг, коллега, однокурсник. Теперь просматривая строку я могу выделить нужные мне части информации. Это удобно и ничего более. Причем здесь больше удобства даже не для визуального восприятия (это спорно), а для программной обработки — достаточно несложно написать программу, которая найдет конкретные кусочки.

Теперь новичкам надо посмотреть какой-нибудь XML, чтобы увидеть больше примеров и убедиться, что в главном я прав �� (хотя все в мире относительно).

Работа с XML

В первую очередь я хотел бы высказать свою позицию по поводу самого XML и уже на основе этого продолжать повествование.
Для меня XML — очень мощная технология, которая позволяет хранить, передавать и обрабатывать сложноструктурированные данные. Т.е. если я хочу иметь: список фирм с их телефонами и счетами, каталог книг с авторами и отзывами, описание структуры страниц сайта с комментариями, состояние всех автобусов в городе с их координатами, водителями, номерами и прочая — все это может быть удобно сохранено в виде XML и, что крайне важно и удобно, может быть передано в любую систему, которая написана на любой платформе — на .NET, PHP, Object C, Delphi, C++.
Проведите мысленный эксперимент — попробуйте написать строку, в которой передать информацию о своих контактах (где у одной персоны может быть несколько телефонов, e-mail, любимые книги, места работы, места учебы и … да хватит пока). Что важно — это должна быть обычная строка (несколько строк), которая позволяет разбирать эту информацию в ту структуру, которую я описал — класс Java. Там надо предусмотреть какие-то разделители, информацию об именах полей (группах полей). Попробуйте — и вы придете к чему-то подобному XML.

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

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

  1. Разбор. Надо уметь разобрать строку на что-то более удобное для обработки — пытаться вставить внутрь строки или находить какое-то поле определенной записи из строки — это достаточно неудобно. Значит нам надо иметь некоторый набор классов для представления нашей строки в виде структуры объектов.
  2. Поиск. По структуре данных надо уметь что-то искать. Причем не подстроку, а какую-то группу полей, которые относятся к определенному объекту — например полная информация о книге — наименование, авторы, отзывы. Или список контактов с фамилией “Сидоров”.
  3. Проверка. Данные должны быть корректными, т.е. там должны быть только определенные поля, с определенным наполнением и они должны быть правильно скомпанованы в нашей строке.
  4. Преобразование. Хоть XML достаточно удобно описывает структурированные данные, это не значит, что его удобно просматривать обычному человеку или всегда удобно обрабатывать. Нередко для решения этого вопроса требуется преобразовать XML в какое-либо другое текстовое представление — например в тот же HTML (который является частным воплощением XML). Или даже в обычный текст.

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

Разбор — Parsing

В слэнге программистов часто используется слова “парсинг”, который и обозначает разбор строки (или еще чего-нибудь) в какую-то структуру. Здесь надо выделить два момента:

  1. Разбор строки определенным алгоритмом
  2. Сохранение результатов разбора в какую-то структуру вместо строки — ибо со строкой многие операции делать просто неудобно.

Что касается второго пункта, то на сегодня существует по сути одна унифицированная структура, которая называется Document Object Model (DOM).
DOM представляет собой набор интерфейсов (и их реализаций), которые являются специализированными объектами для хранения “узлов” (node) XML-документа. По сути каждый тэг — это “узел” (нода — я буду использовать этот термин, т.к. очень привык). Информация внутри тэга — тоже нода. По сути любой разобранный XML — это набор элементов типа Node и еще более специализированных, построенных в дерево.
Почему дерево ? Да потому что у каждой ноды может быть список дочерних нод и у каждой из них тоже может быть “детки”. Так и строится дерево. Если вам сложно это увидеть, то советую посмотреть какую-либо классическую книгу по алгоритмам и структурам данных — можно старого доброго Никлауса Вирта «Алгоритмы и структуры данных». Книгу можно найти в интернете, ну или купить.

Давайте рассмотрим загрузку файла и редактирование построенного дерева на примере. Наша программа считывает XML-файл со списком книг и печатает их свойства. Сам XML-файл выглядит вот так:

Java XML

J ava Development Kit поставляется с двумя парсерами XML: DOM и SAX, каждый из которых имеет свои сильные и слабые стороны. В этом руководстве мы рассмотрим несколько примеров создания, изменения и чтения XML файлов средствами библиотек DOM, SAX и JDOM.

Кроме этого, будут рассмотрены примеры использования библиотеки JAXB для преобразования Java объектов в XML файлы и обратно.

DOM XML парсер

DOM XML парсер — наиболее простой способ работы с XML файлами в Java. При работе с XML файлами производится разбор всего файла, строится его объектная модель, которая полностью загружается в память. Для каждого XML элемента создается свой объект, между которыми организуется удобный способ навигации. DOM XML парсер не рекомендуется использоваться при работе с XML файлами большого размера: с такими файлами работа происходит очень медленно и расходуется очень большое количество памяти.

  • Чтение XML файла средствами DOM XML
    Прочитать XML файл и распечатать каждый из его элементов.
  • Внесение изменений в XML файл средствами DOM XML
    Внесение изменений в существующий XML файл: изменить XML элемент, изменить значения атрибутов, добавить и удалить XML элемент.
  • Создание XML файла средствами DOM XML
    Создать новый XML файл, в котором определены новый документ, XML элементы и добавлены атрибуты.
  • Подсчет XML элементов в файле средствами DOM XML
    Отыскать все XML элементы в файле и подсчитать их количество.

SAX XML парсер

SAX XML парсер работает не так, как DOM: он не читает весь XML файл целиком, не загружает его в память и не создает объекты для каждого элемента. Вместо этого, SAX парсер использует функцию обратного вызова (callback function) org.xml.sax.helpers.DefaultHandler , с помощью которой информирует клиента об изменении структуры XML документа.

Техника работы станет более понятно после рассмотрения конкретных примеров использования SAX XML парсера.

  • Чтение XML файла средствами SAX XML
    Прочитать XML файл с помощью SAX функции обратного вызова.

JDOM XML парсер

Библиотека JDOM XML позволяет представить XML документ в простой и понятной форме, удобной для чтения и изменения данных. JDOM XML является полноценной альтернативой SAX и DOM.

  • Чтение XML файла средствами JDOM XML
    Прочитать XML файл с помощью JDOM и распечатать каждый из элементов.
  • Внесение изменений в существующий XML файл средствами JDOM XML
    Внесение изменений в существующий XML файл: изменить XML элемент, изменить значения атрибутов, добавить и удалить XML элемент.
  • Создание XML файла средствами JDOM XML
    Создать новый XML файл, в котором определены новый документ, XML элементы и добавлены атрибуты.

Использование JAXB аннотаций для преобразования Java объектов в XML и обратно.

Илон Маск рекомендует:  Что такое код ingres_field_scale
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL