Подтвердить что ты не робот

Что означает "@* | node()" в XSLT-методе выбора шаблона?

Я прочитал несколько примеров XSLT и нашел, что код:

<xsl:apply-template select="@*|node()"/>

Что это значит?

4b9b3361

Ответ 1

В выражении XPath @* | node() выбирается объединение узлов атрибутов (@*) и всех других типов узлов XML (node()).

Это сокращение для attribute::* | child::node().

В XSLT XPath относится к контексту node, а ось выбора , например, в <xsl:apply-templates>) соответствует всем атрибутам и другим узлам независимо от контекста (при использовании в качестве выражения match="" в <xsl:template>) - обратите внимание, что существует разница между выбором узлов и их сопоставлением: контекст node имеет значение только для выбора.

Представьте, что следующий node - это контекст node:

<xml attr="value">[
  ]<child />[
  ]<!-- comment -->[
  ]<child>
    <descendant />
  </child>[
]</xml>

выражение node() будет не только выбирать узлы <child>, но также и четыре текстовых узла только для пробелов (обозначаемых [ и ] для видимости) и комментарий. <descendant> не выбран.

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

Это асимметричное соотношение делает необходимым выбирать их отдельно, следовательно @*.

Он соответствует любому атрибуту node, принадлежащему контексту node, поэтому также будет выбран attr="value".

| - оператор объединения XPath. Он создает сингл node из двух отдельных наборов node.

<xsl:apply-templates> затем находит подходящий <xsl:template> для каждого выбранного node и запускает его для этого node. Это совпадающая с шаблоном часть, упомянутая выше.

Ответ 2

Чтобы добавить к Tomalak отличный ответ:

В большинстве случаев можно было бы увидеть <xsl:apply-template select="@*|node()"/> в шаблоне, подобном этому:

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

Это называется правило идентификации или "шаблон идентификации".

Одним из наиболее фундаментальных и мощных шаблонов проектирования XSLT является использование и переопределение правила идентификации.

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

Почему возникает этот результат?

Короткий ответ: из-за модели обработки XSLT.

Более подробное объяснение должно начинаться с верхнего:

node()

соответствует любому элементу, text- node, комментарию или обработке-инструкции. Документ (корневой) - node также соответствует node().

Мы можем представить "листовые" узлы любого дерева документов - это любые узлы, у которых нет самих детей, таких как text- node, комментарий и инструкция обработки. Пустой элемент также следует рассматривать как лист node.

Правило идентичности первоначально выбирается для выполнения (применяется) ко всем дочерним узлам узлов документа (это самые верхние элементы и любые комментарии или братья-переводчики-инструкции, которые он мог бы иметь). Согласованный node неглубоко скопирован, и если это неэлементный лист node, команда <xsl:apply-templates select="node()|@*"/> не выбирает ни узлы, ни атрибуты.

Если совпадающий node - это элемент, он неглубоко копируется, то команда <xsl:apply-templates select="node()|@*"/> вызывает тот же шаблон (как и никакой другой шаблон в коде преобразования), который применяется к каждому из его атрибутов и каждый из его дочерних узлов.

Это рекурсия, которая управляет обработкой каждого node документа XML до тех пор, пока не будут достигнуты листовые узлы или атрибуты, и в этом месте <xsl:apply-templates select="node()|@*"/> не будет выбран ни один из дочерних элементов или узлов-атрибутов.

Ответ 3

Поздравляем @Tomalak за первый правильный ответ. Тик должен идти по его ответу. Я просто добавлю некоторые пояснения к его ответу.

Примечание 1

... @* | node() выбирает объединение...

The | оператор не просто возвращает объединение двух операндов, но сортирует в порядке документа и удаляет дубликаты. Дедупликационная часть здесь неактуальна, потому что нет дубликатов для удаления, но следует отметить часть сортировки. Более правильным вариантом было бы сказать...

... @* | node() выбирает объединение, отсортированное по порядку документа...

Примечание два

... и все другие типы дочерних узлов XML (node())

Это в целом верно, но вводит в заблуждение. Когда большинство людей читают "дочерние узлы XML", они считают дочерние узлы в смысле DOM. Но это не то, что выбрано. Выбраны только узлы XDM. Для иллюстрации взгляните на следующий документ.

<?xml version="1.0" encoding="ISO-8859-1"?>
<root-element my-attrib="myattrib-vaue" xmlns:hi="www.abc.com"><child-element />
abc&apos;def
</root-element>

Теперь предположим, что элемент контекста является "корневым элементом". Читателю ответа Томалака задается вопрос: что выбрано "@* | node()"? Импликация ответа Томалака для тех, кто думает о модели DOM, состоит в том, что выбрано 6 вещей:

  • Атрибут my-attrib
  • Атрибут node -space (который является истинным атрибутом в DOM)
  • Детский элемент node
  • бит 'abc'
  • Ссылка на сущность
  • бит "def".

Но в XSLT это не так. Фактически выбран...

  • Атрибут my-attrib
  • Детский элемент node
  • Текст XDM node, являющийся конкатенацией трех текстовых узлов DOM, таких как: "abc'def"

Таким образом, более точное утверждение будет...

Выражение XPath @* | node() выбирает объединение, отсортированное по порядку документа, (узлов атрибута элемента контекста и дочерних узлов XML элемента контекста в смысле XDM). XD-модель игнорирует некоторые типы node, такие как определения сущностей, которые находятся в DOM, а непрерывные текстовые узлы DOM объединяются в один текст XDM node.