XSL Как обновить значение параметра для расчета итога

У меня есть следующий xml

<?xml version="1.0" encoding="UTF-8"?>
<Results>
  <form-type>orderform-A</form-type>
    <data>
      <form-data>
         <field>
           <name>productid-1</name>
           <value>Yes</value>
         </field>
         <field>
           <name>productid-3</name>
           <value>Yes</value>
         </field>
         <field>
           <name>productid-4</name>
           <value>Yes</value>
         </field>
      </form-data>
   </data>
</Results>

В форме заказа клиент может заказать следующие продукты

  • productid-1 (стоимость $5)
  • productid-2 (стоимость $5)
  • productid-3 (стоимость $5)
  • productid-4 (стоимость $5)

productid-4 при заказе вместе с productid-2 или productid-3 предлагается бесплатно. Обратите внимание, что в форме заказа будут перечислены только заказанные товары.

Точно так же у меня есть следующая форма заказа, которая также позволяет клиентам заказывать несколько количеств каждого продукта:

<?xml version="1.0" encoding="UTF-8"?>
<Results>
  <form-type>orderform-B</form-type>
    <data>
      <form-data>
        <field>
           <name>productid-w</name>
           <value>Yes</value>
        </field>
        <field>
           <name>productid-w-qty</name>
           <value>1</value>
         </field>
         <field>
            <name>productid-x</name>
            <value>Yes</value>
         </field>
         <field>
            <name>productid-x-qty</name>
            <value>1</value>
         </field>
         <field>
            <name>productid-y</name>
            <value>Yes</value>
         </field>
         <field>
            <name>productid-y-qty</name>
            <value>1</value>
         </field>
      </form-data>
    </data>
  </Results>

В форме заказа-B клиент может заказать следующие продукты

  • productid-w (стоимость 20 долларов США)
  • productid-x (стоимость 10 долларов)
  • productid-y (стоимость $20)
  • productid-z (стоимость 10 долларов США)

Я хочу рассчитать общую стоимость каждого заказа, поэтому я пробовал следующее:

 <xsl:param name="form-type">
 <xsl:param name="total">0</xsl:param>

 <xsl:template match="/">
     <xsl:choose>
          <xsl:when test="$form-type = 'orderform-A'">
               <xsl:call-template name="orderform-A-total"/>
          </xsl:when>
          <xsl:when test="$form-type = 'orderform-B'">
                 <xsl:call-template name="orderform-B-total"/>
          </xsl:when>
    </xsl:choose>
</xsl:template>

<xsl:template name="orderform-A-total">
      <xsl:if test="count(//Results/data/form-data/field[name='productid-1']/value) > 0">
          <xsl:value-of select="$total + 5" />
      </xsl:if>
      <xsl:if test="count(//Results/data/form-data/field[name='productid-2']/value) > 0">
           <xsl:value-of select="$total + 5" />
      </xsl:if>
      <xsl:if test="count(//Results/data/form-data/field[name='productid-3']/value) > 0">
            <xsl:value-of select="$total + 5" />
       </xsl:if>
       <xsl:if test="(count(//Results/data/form-data/field[name='productid-4']/value > 0)">
             <xsl:value-of select="$total + 5" />
       </xsl:if>
       <xsl:value-of select="$total" /></value>
 </xsl:template>

 <xsl:template name="orderform-B-total">
           // TO DO
 </xsl:template>    

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

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

michael.hor257k 18.11.2022 20:03

В форме А могут быть повторяющиеся элементы? Что, если продукт4 заказан дважды, а продукт2 или продукт3 — только один раз?

Sebastien 18.11.2022 20:26

@Sebastien в форме A не будет дубликатов.

adam78 18.11.2022 21:40

@ michael.hor257k Я могу использовать xslt 2.0. Я думал, что неизменяемыми являются только переменные, но как насчет параметров, которые я пробовал?

adam78 18.11.2022 21:42

То же самое с параметрами. Вы можете использовать параметр в рекурсивном шаблоне/функции и обновлять его при каждом вызове, но я не думаю, что это подойдет для вашей ситуации.

michael.hor257k 18.11.2022 22:06
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
0
5
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

На вашем месте я бы, наверное, сделал что-то вроде:

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:variable name="pricelist">
    <item id="productid-1">5</item> 
    <item id="productid-2">5</item> 
    <item id="productid-3">5</item> 
    <item id="productid-4">5</item> 
</xsl:variable>

<xsl:key name="price" match="item" use="@id" />

<xsl:template match="/">
    <total>
        <xsl:apply-templates/>
    </total>    
</xsl:template>

<xsl:template match="Results[form-type='orderform-A']">
    <xsl:variable name="charges">
        <xsl:apply-templates select="data/form-data/field"/>
    </xsl:variable>
    <xsl:value-of select="sum($charges/charge)" />
</xsl:template>

<xsl:template match="field">
    <charge>
        <xsl:value-of select="key('price', name, $pricelist)"/>
    </charge>   
</xsl:template>


<xsl:template match="Results[form-type='orderform-B']">
    <!-- TO DO -->
</xsl:template>
 
</xsl:stylesheet>

Для реализации такого правила, как:

productid-4 при заказе вместе с productid-2 или productid-3 предлагается бесплатно

вы можете добавить пустой шаблон, например:

<xsl:template match="field[name='productid-4'][../field[name='productid-2' or name='productid-3']]"/>

Обратите внимание, что нет необходимости в параметре form-type, когда на входе есть элемент form-type.


Добавлен:

Чтобы обработать вариант orderform-B, вы можете сделать:

<xsl:template match="Results[form-type='orderform-B']">
    <xsl:variable name="charges">
        <xsl:apply-templates select="data/form-data/field[value='Yes']" mode="B"/>
    </xsl:variable>
    <xsl:value-of select="sum($charges/charge)" />
</xsl:template>

<xsl:template match="field" mode="B">
    <xsl:variable name="price" select="key('price', name, $pricelist)" />
    <xsl:variable name="qty" select="following-sibling::field[1]/value" />
    <charge>
        <xsl:value-of select="$price * $qty"/>
    </charge>   
</xsl:template>

И, конечно же, вы также должны добавить элементы в переменную $pricelist.

почему выражение соответствия для шаблона формы заказа-B включает/data/form-data? Кроме того, как мне реализовать форму заказа-B, поскольку она включает количество?

adam78 19.11.2022 16:40

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

michael.hor257k 19.11.2022 17:12

это работает, но как я могу получить количество по его имени, поскольку поле количества продукта не всегда может отображаться как следующий брат или сестра, однако соглашение об именовании количества всегда будет именем продукта с суффиксом количества, например. productid-w-qty?

adam78 19.11.2022 21:26

Определите ключ, соответствующий полю по имени, и используйте его, добавив суффикс "-qty" к имени продукта. --- П.С. Если у вас есть какой-либо контроль над форматом ввода, вы можете сэкономить много работы.

michael.hor257k 20.11.2022 04:55

Я создал ключ для qty <xsl:key name="qty" match="field[ends-with(name, '-qty')]" use="name" />, но когда я вызываю его внутри шаблона <xsl:variable name="qty" select="key('qty', name)" /> возвращает и имя, и значение. Как получить только значение? Кроме того, если в форме есть другие поля, не определенные в переменной прайс-листа, я получаю ошибку преобразования строки в двойную. Я решаю это, заворачивая заряд в тест <xsl:if test="key('price', dfor:name, $pricelist)">?

adam78 21.11.2022 16:34

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

michael.hor257k 21.11.2022 17:00

также у меня нет большого контроля над вводом, но я полагаю, что шаблоны можно было бы сократить до использования одного. Просто в некоторых формах есть поле qty, а в других нет, поэтому, если форма не включает qty, тогда qty можно принять равным 1. В этом случае мне нужно будет проверить тип формы, мне просто нужно выяснить, как использовать расчет цены * количества для поддержки обоих типов форм?

adam78 21.11.2022 17:06

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