This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
И, допустим, нас интересует только значение тега material (которого, кстати, может и не быть).
Напишем такую версию simple transformation:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Применение данной трансформации вызовет исключительную ситуацию, так как в XML нам встретиться тег prod и тег foo, которые мы не предусмотрели в трансформации.
Конечно, их можно добавить в трансформацию и никак не обрабатывать их значения. Но таких ненужных нам тегов может быть много и прописывать их все это некомильфо. Кроме того, могут быть ситуации, когда XML описан не четко и подразумевает, что внутри values могут появляться не известные нам на этапе разработки теги.
Как пропускать все что нам не нужно или мы не знаем что это?
Для этого нужно в конец tt:group добавить tt:skip следующим образом:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Здесь мы "говорим", что если нам встречается тег material, то мы берем его значение и помещаем в ROOT.MATERIAL, иначе мы пропускаем 1 тег.
Тег tt:group работает как цикл + switch/case - берет на каждом шаге следующий тег в values и сравнивает по условиям tt:d-cond, если условие проходит - выполняется то, что внутри tt:d-cond, и происходит следующая итерация "цикла". Таким образом, по примеру выше, мы найдем на первой итерации тег material, запишем его значение в root.material, найдем на следующей итерации prod и пропустим его, далее найдем на следующей итерации foo и также пропустим его (и аналогично для других тегов если они будут) и выйдем из values. Тег tt:skip должен быть в конце tt:group.
Но с данной реализацией есть одна неприятность. Толи это баг в реализации SimpleTransfomation, толи это by design. Заключается она в следующем:
Если в исходном XML будет только тег material, это также вызовет ошибку трансформации. Отладка данного случая показывает, что обработав тег material, парсер все равно пытается выполнить tt:skip хотя бы один раз. Делает он это для следующего тега, которым будет закрывающий тег </values>. В итоге правило для самого values не найдет своего закрывающего тега и будет выброшено исключение. Но если в XML есть хотя бы один тег, который нам надо пропустить, то tt:skip сработает 1 раз и далее не будет пытаться пропустить </values>.
Обойти это можно, явно добавив еще один фиктивный тег в конец набора тегов в values в исходном XML. Сделать это можно перед вызовом трансформации например так (XML находится в переменной gv_xml):
а в трансформацию явно добавить обработку тега dummyEnd:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Не понятно почему, но данный подход срабатывает, и после обработки dummyEnd парсер не пытается выполнить tt:skip.
Если же работать перестанет, то есть более сложный, но более логичный вариант трансформации (в XML также все еще нужно добавлять фиктивный тег):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Здесь мы заводим переменную skip. Далее при начале обработки тега values мы записываем в переменную skip значение 0. В условии tt:cond-var check="skip=0" мы проверяем, что skip равно 0 и, если это так, то пропускаем один тег с помощью tt:skip. Если мы встречаем тег dummyEnd, то записываем в переменную skip значение 1. Таким образом, после последнего тега в values (а мы позаботились чтобы им был dummyEnd), больше не требуется пропускать теги, tt:skip не будет выполнен, и будет обработан закрывающий </values>