Мне нравится твой вопрос. Вы очень четко формулируете то, чего еще не понимаете. Вам просто нужно что-то связать. Я рекомендую вам прочитать «Как работает XSLT», главу, которую я написал для того, чтобы вопросы, которые вы задаете. Я хотел бы услышать, связывает ли это вас воедино.
Менее формально, я постараюсь ответить на каждый из ваших вопросов.
- В каком порядке выполняются шаблоны и
- Когда они выполняются, соответствуют ли они (а) исходному исходному XML или (б) текущему выходу XSLT для этой точки?
В любой момент обработки XSLT существует, в некотором смысле, два контекста, которые вы определяете как (a) и (b): где вы находитесь в дереве исходных кодов и где находитесь. дерево результатов. Место, где вы находитесь в дереве исходных текстов, называется текущим узлом. Он может меняться и перемещаться по всему дереву исходного кода, когда вы выбираете произвольные наборы узлов для обработки с помощью XPath. Однако концептуально вы никогда не «перепрыгиваете» по дереву результатов таким же образом. Процессор XSLT строит его упорядоченным образом; сначала он создает корневой узел результирующего дерева; затем он добавляет потомков, выстраивая результат в порядке документа (в глубину). [Ваш пост побуждает меня снова взять мою программную визуализацию для экспериментов XSLT ...]
Порядок шаблонных правил в таблице стилей не имеет значения. Вы не можете сказать, просто взглянув на таблицу стилей, в каком порядке будут создаваться правила шаблона, сколько раз будет создаваться правило или даже будет ли оно вообще. (match="/" - исключение; вы всегда можете знать, что он сработает.)
Я предполагаю, что шаблон № 1 будет выполнен первым. Я не знаю, почему я так предполагаю - просто потому, что это указано первым в документе?
Неа. Он будет вызываться первым, даже если вы поместите его последним в документе. Порядок правил шаблона никогда не имеет значения (за исключением состояния ошибки, когда у вас есть несколько правил шаблона с одинаковым приоритетом, соответствующих одному и тому же узлу; даже в этом случае это необязательно для разработчика, и вы никогда не должны полагаться на такое поведение). Он вызывается первым, потому что первое, что всегда происходит при запуске процессора XSLT, - это виртуальный вызов <xsl:apply-templates select="/"/> . Один виртуальный вызов строит все дерево результатов. Вне него ничего не происходит. Вы можете настроить или «сконфигурировать» поведение этой инструкции, определив правила шаблона.
Будет ли выполняться шаблон №2? Он соответствует узлу в исходном XML, но к тому времени, когда мы дойдем до этого шаблона (при условии, что он будет запущен вторым), узел «firstName» не будет в выходном дереве.
Шаблон №2 (или любые другие правила шаблона) никогда не сработает, если у вас нет вызова <xsl:apply-templates/> где-нибудь в правиле match="/". Если у вас их нет, то никакие правила шаблона, кроме match="/", не сработают. Подумайте об этом так: для того, чтобы сработало правило шаблона, оно не может просто соответствовать узлу во входных данных. Он должен соответствовать узлу, который вы выбрали для обработки (используя <xsl:apply-templates/>). И наоборот, он будет продолжать сопоставлять узел столько раз, сколько вы выберете для его обработки.
Будет ли [шаблон match="/"] препятствовать выполнению всех остальных шаблонов, поскольку после того, как этот первый шаблон будет завершен, не будет ничего, с чем можно было бы сопоставить?
Это правило нигде не вытесняет остальных, включая <xsl:apply-templates/>. В исходном дереве все еще есть множество узлов, которые можно обработать. Они всегда все здесь, готовые к сбору; обрабатывайте каждый столько раз, сколько хотите. Но единственный способ обработать их с помощью правил шаблона - вызвать <xsl:apply-templates/>.
До сих пор я был обеспокоен тем, что более поздние шаблоны не выполняются, потому что узлы, с которыми они работали, не отображаются в выходных данных, но как насчет обратного? Может ли «более ранний» шаблон создать узел, с которым «более поздний» шаблон может что-то делать?
Дело не в том, что «более ранний» шаблон создает новый узел для обработки; дело в том, что «более ранний» шаблон, в свою очередь, обрабатывает больше узлов из исходного дерева, используя ту же самую инструкцию (<xsl:apply-templates). Вы можете думать об этом как о рекурсивном вызове одной и той же «функции» с разными параметрами каждый раз (узлы для обработки, определенные контекстом и атрибутом select).
В итоге вы получаете древовидный стек рекурсивных вызовов одной и той же «функции» (<xsl:apply-templates>). И эта древовидная структура изоморфна вашему фактическому результату. Не все осознают это или думали об этом таким образом; это потому, что у нас нет эффективных инструментов визуализации ... пока.
Шаблон №1 создает новый узел с именем «fullName». Шаблон № 2 соответствует тому же узлу. Будет ли шаблон № 2 выполняться, потому что узел «fullName» существует в выходных данных к тому времени, когда мы дойдем до шаблона № 2?
Неа. Единственный способ создать цепочку обработки - это явно настроить ее таким образом. Создайте переменную, например $tempTree, которая содержит новый элемент <fullName>, а затем обработайте его, как это <xsl:apply-templates select="$tempTree">. Чтобы сделать это в XSLT 1.0, вам нужно заключить ссылку на переменную в функцию расширения (например, exsl:node-set()), но в XSLT 2.0 она будет работать так же, как есть.
Независимо от того, обрабатываете ли вы узлы из исходного исходного дерева или во временном дереве, которое вы создаете, в любом случае вам нужно явно указать, какие узлы вы хотите обработать.
Мы не рассмотрели то, как XSLT получает все свое неявное поведение. Вы также должны понимать правила встроенного шаблона. Я постоянно пишу таблицы стилей, которые даже не включают явного правила для корневого узла (match="/"). Вместо этого я полагаюсь на встроенное правило для корневых узлов (применять шаблоны к дочерним узлам), которое аналогично встроенному правилу для узлов элементов. Таким образом, я могу игнорировать большие части ввода, позволить процессору XSLT автоматически проходить его, и только когда он наткнется на интересующий меня узел, я сделаю что-то особенное. Или я мог бы написать одно правило, которое рекурсивно копирует все (так называемое преобразование идентичности), переопределяя его только там, где это необходимо, для внесения дополнительных изменений во входные данные. После того, как вы прочитали «Как работает XSLT», ваше следующее задание - найти «преобразование идентичности».
Я понимаю, что совершенно не осведомлен о "дзен" XSLT. На сегодняшний день мои таблицы стилей состояли из шаблона, соответствующего корневому узлу, а затем стали полностью процедурными. Я устал этим заниматься. Я бы предпочел правильно понять XSLT, отсюда и мой вопрос.
Я вам аплодирую. Пришло время принять «красную таблетку»: прочтите «Как работает XSLT»
person
Evan Lenz
schedule
09.10.2009