XSLT: суммировать и удалять узлы XML в зависимости от условий

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

Пояснение: У каждой статьи есть идентификатор, название, цена и номер копии. В моем случае у меня всегда есть две копии. Копия 0 и Копия 1. Если статья имеет две копии, то мы добавляем цену копии статьи 1 в копию статьи 0 и исключаем копию 1 из вывода.

Я не совсем уверен, как подойти к этому требованию.

XML-вход

<?xml version = "1.0" encoding = "UTF-8"?>
<wd:Report_Data>
  <wd:Report_Entry>
    <wd:id>1000</wd:id>
    <wd:name>Call of Duty</wd:name>
    <wd:price>50.12</wd:price>
    <wd:copy>0</wd:copy>
  </wd:Report_Entry>
  <wd:Report_Entry>
    <wd:id>1000</wd:id>
    <wd:name>Call of Duty</wd:name>
    <wd:price>60.0</wd:price>
    <wd:copy>1</wd:copy>
  </wd:Report_Entry>
  <wd:Report_Entry>
    <wd:id>2000</wd:id>
    <wd:name>Metal Slug</wd:name>
    <wd:price>75.00</wd:price>
    <wd:copy>0</wd:copy>
  </wd:Report_Entry>
  <wd:Report_Entry>
    <wd:id>3000</wd:id>
    <wd:name>Need For Speed</wd:name>
    <wd:price>40.00</wd:price>
    <wd:copy>0</wd:copy>
  </wd:Report_Entry>
</wd:Report_Data>

Ожидаемый вывод XML:

<?xml version = "1.0" encoding = "UTF-8"?>
<wd:Report_Data>
  <wd:Report_Entry>
    <wd:id>1000</wd:id>
    <wd:name>Call of Duty</wd:name>
    <wd:price>110.12</wd:price>
    <wd:copy>0</wd:copy>
  </wd:Report_Entry>
  <wd:Report_Entry>
    <wd:id>2000</wd:id>
    <wd:name>Metal Slug</wd:name>
    <wd:price>75.00</wd:price>
    <wd:copy>0</wd:copy>
  </wd:Report_Entry>
  <wd:Report_Entry>
    <wd:id>3000</wd:id>
    <wd:name>Need For Speed</wd:name>
    <wd:price>40.00</wd:price>
    <wd:copy>0</wd:copy>
  </wd:Report_Entry>
</wd:Report_Data>

Следуя рекомендации @michael.hor257k, мне удалось создать структуру группировки и просуммировать цену. Однако ожидаемого результата я так и не получил

XSLT

<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:stylesheet version = "2.0" xmlns:wd = "http://www.workday.org/" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:xs = "http://www.w3.org/2001/XMLSchema">
    <xsl:template match = "/">
            <xsl:for-each-group select = "wd:Report_Data/wd:Report_Entry" group-by = "wd:id">
                <xsl:copy>
                    <xsl:copy-of select = "wd:id"/>
                    <xsl:copy-of select = "wd:name"/>
                    <wd:price>
                        <xsl:value-of select = "sum(current-group()/wd:price)" />
                    </wd:price>                 
                    <xsl:copy-of select = "wd:copy"/>
                </xsl:copy>
            </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

Результат (не тот, что я хочу)

<wd:Report_Entry xmlns:wd = "http://www.workday.org/">
   <wd:id>1000</wd:id>
   <wd:name>Call of Duty</wd:name>
   <wd:price xmlns:xs = "http://www.w3.org/2001/XMLSchema">110.12</wd:price>
   <wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry xmlns:wd = "http://www.workday.org/">
   <wd:id>2000</wd:id>
   <wd:name>Metal Slug</wd:name>
   <wd:price xmlns:xs = "http://www.w3.org/2001/XMLSchema">75</wd:price>
   <wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry xmlns:wd = "http://www.workday.org/">
   <wd:id>3000</wd:id>
   <wd:name>Need For Speed</wd:name>
   <wd:price xmlns:xs = "http://www.w3.org/2001/XMLSchema">40</wd:price>
   <wd:copy>0</wd:copy>
</wd:Report_Entry>

В этом нет ничего «хитрого»; это основная проблема группировки. Выполните поиск — это, вероятно, наиболее часто задаваемый здесь вопрос о XSLT. Обратите внимание, что ответы различаются для XSLT 1.0 или 2.0 и выше.

michael.hor257k 13.08.2024 19:47

Идеальный. я попробую

David Edgar 13.08.2024 20:32

@michael.hor257k – Не могли бы вы меня немного подсказать? Я понимаю использование таких функций группировки, как (для каждого и для каждой группы). Однако я не понимаю, как построить механизм, который суммирует только в статье (с копией = 0).

David Edgar 14.08.2024 05:37

Я не понимаю сложности: просто сгруппируйте записи по их идентификаторам и просуммируйте цены группы. Группа из 1 — это такая же группа, как и любая другая.

michael.hor257k 14.08.2024 06:06

Вот пример, который вы можете использовать в качестве отправной точки: stackoverflow.com/a/39185213/3016153

michael.hor257k 14.08.2024 06:13

@michael.hor257k — Мой вывод в формате XML выглядит неправильно. Я предполагаю, что проблема связана с выбранным мной путем сопоставления. Я пробовал несколько комбинаций, но безрезультатно

David Edgar 19.08.2024 17:27
Стоит ли изучать 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
6
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вам нужно лишь внести несколько небольших изменений:

<xsl:stylesheet version = "2.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" 
xmlns:wd = "http://www.workday.org/">
<xsl:output method = "xml" indent = "yes"/>

<xsl:template match = "/wd:Report_Data">
    <xsl:copy>
        <xsl:for-each-group select = "wd:Report_Entry" group-by = "wd:id">
            <xsl:copy>
                <xsl:copy-of select = "wd:id"/>
                <xsl:copy-of select = "wd:name"/>
                <wd:price>
                    <xsl:value-of select = "sum(current-group()/wd:price)" />
                </wd:price>                 
                <xsl:copy-of select = "wd:copy"/>
            </xsl:copy>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

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