XSLT 2.0: выбор узла XML путем сопоставления одного дочернего узла и сравнения другого

У меня есть входной XML, как показано ниже:

<parent>
    <payment>
        <id>123456</id>
        <type>CANCELLED</type>
        <date>2020-12-03</date>
        <amount>100</amount>
    </payment>
    <payment>
        <id>234567</id>
        <type>FORCE</type>
        <date>2020-12-01</date>
        <amount>200</amount>
    </payment>
    <payment>
        <id>345678</id>
        <type>CANCELLED</type>
        <date>2020-12-01</date>
        <amount>300</amount>
    </payment>
    <payment>
        <id>456789</id>
        <type>FORCE</type>
        <date>2020-12-01</date>
        <amount>400</amount>
    </payment>
    <payment>
        <id>456788</id>
        <type>CANCELLED</type>
        <date>2020-12-01</date>
        <amount>500</amount>
    </payment>
</parent>

Теперь нам нужны узлы, где тип = «ОТМЕНЕН», и в этих отмененных платежах находится сложное условие, если дата равна, нам нужно выбрать узел с самым высоким идентификатором. Итак, в приведенном выше образце ввода должны быть выбраны только 1-й и 5-й узлы. дата для первого узла не совпадает ни с каким другим узлом, поэтому он выбран. В то время как дата для 5-го узла совпадает с 3-м узлом, но выбран 5-й, поскольку он имеет более высокий идентификатор.

Чтобы добиться этого, я попытался написать ниже XSLT,

<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:strip-space elements = "*"/>
    <xsl:variable name = "input" select = "parent"/>
    <xsl:template match = "/">
        <xsl:for-each select = "parent/payment[type='CANCELLED']">
            <xsl:choose>
                <xsl:when test = "date = $input/payment[type='CANCELLED']/date">
                    <xsl:message>
                        <xsl:value-of select = "amount"/>
                    </xsl:message>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select = "amount"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Для каждого требуется, так как в реальном примере мы извлекаем некоторые значения, поэтому нам нужно настроить условие цикла для каждого или написать условие внутри него. Я попытался объявить ввод переменной со всем входным xml и сравнить узел, который выбирается в рамках каждой итерации, с входным узлом, но затем он также совпадает с самим собой. Я иду в правильном направлении? Пожалуйста, направляйте.

Заранее спасибо.

Стоит ли изучать 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
218
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Чтобы идентифицировать payment с одинаковым date, используйте группировку, затем в каждой группе выберите элемент (ы) с самым высоким/максимальным идентификатором:

<xsl:for-each-group select = "//payment[type = 'CANCELLED']" group-by = "date">
  <xsl:copy-of select = "current-group()[id = max(current-group()/id)]"/>
</xsl:for-each-group>

Спасибо @MartinHonnen. Идеальный !

Swapnil Prabhavalkar 10.12.2020 10:49

Один последующий запрос: когда я делаю max(current-group()/id) , я теряю начальные нули. например, если идентификатор платежа 000004984, он становится 4984. Есть ли способ сохранить начальные нули и одновременно получить максимум?

Swapnil Prabhavalkar 15.02.2021 06:38

@SwapnilPrabhavalkar, подумайте о том, чтобы задать новый вопрос с подробностями, все ли id во входных данных имеют одинаковое количество цифр, можете ли вы жить с сравнением чисел, которое удаляет полосы ведущих нулей, но позволит вам позже использовать, например, `format-integer(max(current-group()/id), '0000000000') для форматирования максимального значения до желаемого количества цифр?

Martin Honnen 15.02.2021 11:42

Спасибо @MartinHonnen. Я исправил проблему, используя номер формата, поскольку количество цифр было исправлено (10).

Swapnil Prabhavalkar 19.02.2021 06:54

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