Конкатенация или объединение последовательностей при использовании оператора "кроме"

Я пытаюсь понять разницу (или ее отсутствие) между использованием конкатенации последовательностей или объединения последовательностей в этом случае, например:

Входной XML:

<?xml version = "1.0" encoding = "utf-8" ?>
<document>
  <someElement a = "1" b = "2" c = "3" d = "4"/>
</document>

XSLT:

<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
    version = "3.0">

  <xsl:mode on-no-match = "shallow-copy"/>

  <xsl:output method = "xml" indent = "yes"/>

  <xsl:template match = "someElement">
    
    <xsl:copy>
      <xsl:copy-of select = "@* except (@c, @d)"/>
    </xsl:copy>
    
    <xsl:copy>
      <xsl:copy-of select = "@* except (@c | @d)"/>
    </xsl:copy>
    
  </xsl:template>
  
</xsl:stylesheet>

Выход:

<?xml version = "1.0" encoding = "UTF-8"?>
<document>
   <someElement a = "1" b = "2"/>
   <someElement a = "1" b = "2"/>
</document>

Поэтому я использовал xsl:copy с оператором exclude, как описано на стр. 261 или XSLT и XPath доктора Кея, 4-е изд. книга. Там запятая используется для построения последовательности.
Я также пробовал с оператором унинон и получил тот же результат. На странице 537 операторы определены как:

  • , : Конкатенация последовательности

  • | union : Объединение двух последовательностей, рассматриваемых как наборы узлов.

Итак, при использовании любого из них есть разница?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
77
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Когда вы создаете последовательность с помощью оператора запятая, операнды объединяются в том порядке, в котором вы их перечисляете, и последовательность может содержать повторяющиеся элементы.

OTOH, когда вы используете оператор объединения, элементы перечислены в порядке документа, а повторяющиеся узлы удаляются.

Вот более наглядный пример:

XML

<root>
    <alpha/>
    <bravo/>
    <charlie/>
</root>

XSLT 2.0

<xsl:stylesheet version = "2.0" 
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "xml" version = "1.0" encoding = "UTF-8" indent = "yes"/>

<xsl:template match = "/root">
    <xsl:copy>
        <comma>
            <xsl:copy-of select = "bravo, alpha, charlie, bravo"/>
        </comma>
        <union>
            <xsl:copy-of select = "bravo | alpha | charlie | bravo"/>
        </union>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Результат

<?xml version = "1.0" encoding = "UTF-8"?>
<root>
   <comma>
      <bravo/>
      <alpha/>
      <charlie/>
      <bravo/>
   </comma>
   <union>
      <alpha/>
      <bravo/>
      <charlie/>
   </union>
</root>

Добавлен:

В своем ответе выше я решил проигнорировать часть об операторе исключения и сосредоточиться на различиях между операторами запятой и объединения при построении последовательности.

Как указывалось в других ответах, когда к конструктивному выражению добавляется оператор исключения, эти различия эффективно стираются.

Чтобы продемонстрировать это довольно экстремальным образом, инструкция:

        <except>
            <xsl:copy-of select = "(bravo, alpha, charlie, bravo) except()"/>
        </except>
    
                

при использовании в приведенном выше примере будет производиться:

   <except>
      <alpha/>
      <bravo/>
      <charlie/>
   </except>

Для оператора except, который является оператором «набора», например union, | и intersect, это не имеет значения, поскольку https://www.w3.org/TR/xpath-31/#combining_seq гласит: « Все эти операторы удаляют повторяющиеся узлы из своих результирующих последовательностей на основе идентификатора узла. Результирующая последовательность возвращается в порядке документа».

Ответ принят как подходящий

Выражение X except Y выбирает каждый узел, который находится в X и не находится в Y.

Выражения (P|Q) и (P,Q) доставляют одни и те же узлы, хотя результаты могут быть в другом порядке, а вторая форма может содержать дубликаты. Но поскольку обе формы включают в себя одни и те же узлы, они взаимозаменяемы при использовании в правой части слова «кроме».

Разве (P|Q) не более эффективен, чем (P,Q)?

y.arazim 08.01.2023 20:01

Эффективность полностью зависит от реализации, а также от размеров соответствующих наборов узлов. В общем, оценка (P|Q) требует больше работы, чем оценка (P,Q), но тот факт, что результат находится в порядке документа, может сэкономить работу на последующих этапах. Оптимизатор вполне разумно может переписать как X except (P,Q), так и X except (P|Q) как X except P except Q, и в этом случае, конечно, они оба будут работать одинаково.

Michael Kay 09.01.2023 12:49

Хм. Я подумал, что поскольку (P|Q) содержит меньше информации, чем (P,Q) (порядок, кратность), было бы эффективнее использовать его там, где конечный результат все равно одинаков. Но я думаю, я не знаю, как все работает под капотом.

y.arazim 09.01.2023 14:09

Дьявол кроется в деталях. Если P и Q являются выражениями, использующими дочернюю ось или ось атрибута, вы можете просмотреть ось и проверить каждый узел, чтобы увидеть, совпадают ли они. Если это более сложные выражения, например, вызовы функций, вам придется сортировать результаты в порядке документов и устранять дубликаты в случае «|», работа, которая не требуется в случае «,».

Michael Kay 09.01.2023 19:19

Хорошо. Но я по-прежнему предпочитаю использовать (P|Q), когда меня не волнует порядок, и оставляю использование (P,Q) в тех случаях, когда мне это нужно. Я считаю, что это делает цель кода более ясной.

y.arazim 09.01.2023 20:55

Это похоже на то, что люди продолжают писать author/@name вместо author!@name. Существует естественная тенденция предпочитать конструкции, которые были в языке с самого начала, они кажутся более естественными, несмотря на то, что новые конструкции на самом деле проще и потенциально быстрее.

Michael Kay 10.01.2023 12:55

Я не понимаю, чем причина похожа на тенденцию.

y.arazim 10.01.2023 18:37

Другие вопросы по теме