Pull to refresh

Comments 15

на больших объёмах

Ну вроде как XMLReader и предназначен для работы с БОЛЬШИМИ документами. Ибо работает с потоком, а тот же SimpleXML грузит и парсит весь файл сразу.

XMLReader  работает на очень низком уровне, буквально лексический разбор.

В одной из первых иттераций парсинга, была мысли результат $reader->read() отдавать последователь во все парсеры и таким образом документ бы парсился за один проход.

Но когда другие команды стали писать свои парсеры, они эту идею не оценили, пришлось один и тоот же докумнет передавать в кучу парсеров.

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

Почему я стал искать альтернативу XMLReader  ? Все входящие сообщения у нас парсились на примерно 10-ке парсерах, и вот один из парсеров выполнялся по 2 секунды, при том что этот парсер не находил ни чего для себя интересного, то есть работал в холостую, другие аналогичные парсеры отрабатывали документы за 5-50 мс максимум.

По идее этот неудачный парсер за каждый цикл чтения $reader->read() выполнял около 20-ти раз оператор IF, ине понятно чему там тормозить, когда я переписал его на SimpleXMLElement , время работы сократилось до приемлимых 50мс.

Как мне кажестя SimpleXMLElement не вычитывает весь документ за раз и не строит DOM, SimpleXMLElement вычитывает один элемент (все атрибуты и "иннер текст") за раз и строит только его объектную модель.

Если бы оно выжирало гигабайты памяти (какие то XML у нас реально гигабайты весят), мне бы настучали по голове и по рукам, но этого не произошло: или этого ни разу не было, или админы не успели заметить :)

Сейчас после последней оптимизации на каждый документ вызывается парсер соответствующий его пространству имён. Поэтому сейчас на каждый документ не создаётся по 10+ джоб, создаётся одна или не одной.

Но осадочек остался, с SimpleXMLElement код очень приятно писать, снова чувствуешь себя человеком, а не студентом второго курса пишущем на ассембелере.

Если у бизнес команд горит и им не когда ждать, что бы им написали парсер, то было решено отдавать массив (с помощью Converter).

Кроме того, разным командам в одном и том же документе могут быть интересны разные куски, что бы не заморачиваться, поэтому мы решили всегда отдавать массивом, когда парсинг станет слишком прожорливым - придумаем что ни будь ещё.

Позже я написал объектно ориентированную обёртку над этим массивом (XmlNavigator).

Такая история есл икоротко, и промолчать пр о100500 нюансов.

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

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

Как мне кажестя SimpleXMLElement не вычитывает весь документ за раз и не
строит DOM, SimpleXMLElement вычитывает один элемент (все атрибуты и
"иннер текст") за раз и строит только его объектную модель

Боюсь вам не правильно кажется. Там вроде как есть лимит для библиотеки libxml, но скорее всего вы раньше уткнетесь в память пыха.

Пользуюсь XMLReader, потому что грузить в память 4Gb документы как-то не очень...

Как написать эту статью:

Шаг 1: Не разбиратся в теме, и так сойдет.

Шаг 2: Придумать причину почему вам именно нужен масив

Шаг 3: Обосновать логически (или просто накидать рандомную причину, которой нету)

Шаг 4. Написать пустую статью

Очень смешно читать такие коменты.

Я написал что пользуюсь разными инструментами, в том числе и XMLReader , и SimpleXMLElement, судя по опросу многие делают так же, это называется не разобраться в теме ?

Вы знаете почему надо из документа сделать DTO и отдать на обработку дальше, другой команде ?

Вы знаете что другая команда отказывается иметь дело с XML и ждёт от вас только DTO, максимум на что согласны - на массив ?

Вы знаете что документ который надо распарсить имеет не тривиальную XSD, и уникальных элементов в нём до 300 ?

Времени на задачу у вас два дня от силы. Ваши действия ?

Вы разобрались в теме или и так соёдёт ?

Я не знаю каких в вашей жизни причин нет, а в моей жизни причин хватает :)

плюс совесть грызёт за оверхэд от перебора всех элементов документа

А как работает создание массива из xml? Не в память всё пишет?

Непонятно, зачем нужен *multiple, почему не сделать просто массив или что там у Вас?

attribs() - что Вы делаете с сэкономленным временем? Ну, правда, attributes же гораздо лучше

Кстати, тут немного проблема в терминологии, у Вас тут ассоциативный массив, а не просто массив. В php всё одно вроде, не знаю, но немного сбивает с толку

Плюс, проблема обозначена недостаточно прозрачно

К любому элементу на кириллице можно обратиться не используя xpath. $parent->{'какой то элемент XML'}

Использую sabre/xml на основе XMLReader. Киллер-фича в том что можно через коллбэки распарсить элементы сразу в массивы. Еще одна фича, которая для меня оказалась не менее важной - если распарсить просто в массив и сохранить фрагмент как документ, все пространства имен останутся на месте, SimpleXML имеет свойство их терять

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE

wow?

wow конечно, но лучше не пользоватся таким если нет желания потерять аттрибуты:

<?xml version="1.0" encoding="UTF-8"?>
<GetItemResponse xmlns="urn:ebay:apis:eBLBaseComponents">
    <Item>
        <AutoPay>true</AutoPay>
        <ListingDetails>
            <ConvertedBuyItNowPrice currencyID="USD">0.0</ConvertedBuyItNowPrice>
            <ConvertedStartPrice currencyID="USD">313.6</ConvertedStartPrice>
            <ConvertedReservePrice currencyID="USD">0.0</ConvertedReservePrice>
        </ListingDetails>
    </Item>
</GetItemResponse>
array(1) {
  ["Item"]=>
  array(2) {
    ["AutoPay"]=>
    string(4) "true"
    ["ListingDetails"]=>
    array(3) {
      ["ConvertedBuyItNowPrice"]=>
      string(3) "0.0"
      ["ConvertedStartPrice"]=>
      string(5) "313.6"
      ["ConvertedReservePrice"]=>
      string(3) "0.0"
    }
  }
}

Хм. Велосипедостроение.

Есть три варианта работат с xml, никто пока ничего нового не придумал.

  1. SAX, самый быстрый способ однонаправленного чтения/записис, даёт хорошую производительность при минимальном расходе ресурсоа. Не удобен для чтения и построения сложных обектов, код плохо читаемый.

  2. DOM, модель документа материализуються и работа идёт с верхнеуповневой абстракцией, удобно, просто, легко читаемо. Очень медленно работает, ест память.

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

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

XML ещё жив и иногда его приходиться парсить. Особенно если вы работаете со СМЭВ

Эм... А что, XML нынче кроме как для электрички больше ни для чего не используется?

Или это конкретно для PHP она - основной потребитель XML?

Sign up to leave a comment.

Articles