Согласен, надо быть деликатным с определением search, но хорошего способа автоматизировать и этот процесс лично я пока не вижу (о плохом способе напишу внизу), а если и найдется нетривиальный способ, то не факт, что он отработает лучше человека. Здесь еще важно, кто как вообще привык писать модификации, я делал под себя (в хорошем смысле этого выражения :)).
А мне показалось удобным так: написал и отладил модификацию на чистом opencart, получил ocmod, применил его на другой копии opencart-а и проверил, как все работает. Потом часто делать это не придется, только search проверить. Задание search делал один раз, больше менять его не понадобилось, соответственно, многократная доработка модификации шла «наживую» и только иногда проверялась через генерацию ocmod (например, перед публикацией или если появились новые области кода), да и тогда исправления были легкими. Другими словами, мне отлаживать скрипты проще по принципу сохранил скрипт-обновил страницу без промежуточных звеньев вроде переподгрузки модификаций, а с ocmod заморачиваться уже в конце, и то не сильно.
Кстати, было бы интересно, кто как еще придумал делать ocmod.
А вот плохой способ автоматизации определения search (для тех, кто захочет реализовать/дописать мой скрипт):
— Взять последнюю непустую строку в файле перед нашим кодом, если она есть. Если она уникальна в файле, то сократить до минимума, пока она уникальна. Если неуникальна, то посчитать ее индекс.
— Взять первую непустую строку в файле после нашего кода, если она есть. Если она уникальна в файле, то сократить до минимума, пока она уникальна. Если неуникальна, то посчитать ее индекс.
— Если обе уникальны, выбрать короче, если обе неуникальны, выбрать с меньшим индексом, иначе выбрать уникальную. В зависимости от этого генерить search position=«after» или search position=«before» и при необходимости задавать индекс.
— Если нужен search position=«replace», то особым образом комментировать убираемую строку. Регулярка в этой схеме не используется.
В-общем, например, так — первое, что пришло на ум. Кто захочет, может додумать.
Класс простой и (по возможности) быстрый. Создать конкуренцию по удобству xPath целью не было. За элегантность всегда приходится платить ресурсами. DOM старался не использовать.
Все обработчики реализуются в зависимости от места в структуре, в котором определены. Это в том числе и уровень вложенности.
Обработчик для n-го дочернего элемента можно реализовать условием в теле обработчика. Возможно, получится органично вкрутить эту логику и в метод xmlStruct, если понадобится, пока не думал над этим, т.к. не надобилось.
На мой взгляд, это интересно для тех, кто в силу экономии ресурсов отказался от DOM.
Согласен, можно.
Я старался не загонять XML объектом или массивом в память, т.к. он может быть очень большим. Даже у XMLReader::xml() есть недостаток такого плана — строковый аргумент тела xml, хотя и меньший по объему хранения, нежели в виде объекта (на мой взгляд).
Однако и это обходится — можно, например, наш класс надстроить не над XMLReader, а написать аналогичный по функционалу парсер тегов низкого уровня (это не сложно), который будет читать не из строки, а порционно из файла, например.
Да, я не стал приводить в пример 1С-Bitrix CommerceML2, сберегая время и нервы читателей, хотя для обработки именно 1С-овских файлов написал эту несложную надстройку, что впоследствии сэкономило мне время. Для понимания принципа это посчитал ненужным.
Дебаг оставил намеренно, его убрать несложно — это для тех, кто захочет проверить порядок выполнения.
Постарался реализовать все одним методом, даже в ущерб эстетике, но это критично по производительности.
Да, но в XSD код не запихнешь, а простая проверка структуры — это уже немного другая задача. Структура получается детерминирована в рамках конкретного вызова, и как правило (99%) известна для конкретной задачи и на мой взгляд позволяет просто и быстро написать обработчик, не срывая сроков.
Абсолютно согласен с тем, что XML — не всегда оптимальный вариант представления информации, но зачастую мы можем работать только с тем, что имеем по условию задачи, например, при работе со сторонним API и т.д.
А мне показалось удобным так: написал и отладил модификацию на чистом opencart, получил ocmod, применил его на другой копии opencart-а и проверил, как все работает. Потом часто делать это не придется, только search проверить. Задание search делал один раз, больше менять его не понадобилось, соответственно, многократная доработка модификации шла «наживую» и только иногда проверялась через генерацию ocmod (например, перед публикацией или если появились новые области кода), да и тогда исправления были легкими. Другими словами, мне отлаживать скрипты проще по принципу сохранил скрипт-обновил страницу без промежуточных звеньев вроде переподгрузки модификаций, а с ocmod заморачиваться уже в конце, и то не сильно.
Кстати, было бы интересно, кто как еще придумал делать ocmod.
А вот плохой способ автоматизации определения search (для тех, кто захочет реализовать/дописать мой скрипт):
— Взять последнюю непустую строку в файле перед нашим кодом, если она есть. Если она уникальна в файле, то сократить до минимума, пока она уникальна. Если неуникальна, то посчитать ее индекс.
— Взять первую непустую строку в файле после нашего кода, если она есть. Если она уникальна в файле, то сократить до минимума, пока она уникальна. Если неуникальна, то посчитать ее индекс.
— Если обе уникальны, выбрать короче, если обе неуникальны, выбрать с меньшим индексом, иначе выбрать уникальную. В зависимости от этого генерить search position=«after» или search position=«before» и при необходимости задавать индекс.
— Если нужен search position=«replace», то особым образом комментировать убираемую строку. Регулярка в этой схеме не используется.
В-общем, например, так — первое, что пришло на ум. Кто захочет, может додумать.
Все обработчики реализуются в зависимости от места в структуре, в котором определены. Это в том числе и уровень вложенности.
Обработчик для n-го дочернего элемента можно реализовать условием в теле обработчика. Возможно, получится органично вкрутить эту логику и в метод xmlStruct, если понадобится, пока не думал над этим, т.к. не надобилось.
На мой взгляд, это интересно для тех, кто в силу экономии ресурсов отказался от DOM.
Я старался не загонять XML объектом или массивом в память, т.к. он может быть очень большим. Даже у XMLReader::xml() есть недостаток такого плана — строковый аргумент тела xml, хотя и меньший по объему хранения, нежели в виде объекта (на мой взгляд).
Однако и это обходится — можно, например, наш класс надстроить не над XMLReader, а написать аналогичный по функционалу парсер тегов низкого уровня (это не сложно), который будет читать не из строки, а порционно из файла, например.
Дебаг оставил намеренно, его убрать несложно — это для тех, кто захочет проверить порядок выполнения.
Постарался реализовать все одним методом, даже в ущерб эстетике, но это критично по производительности.