У меня есть следующий 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-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 клиент может заказать следующие продукты
Я хочу рассчитать общую стоимость каждого заказа, поэтому я пробовал следующее:
<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>
Но это не работает. Как рассчитать общую сумму для различных типов форм заказа?
В форме А могут быть повторяющиеся элементы? Что, если продукт4 заказан дважды, а продукт2 или продукт3 — только один раз?
@Sebastien в форме A не будет дубликатов.
@ michael.hor257k Я могу использовать xslt 2.0. Я думал, что неизменяемыми являются только переменные, но как насчет параметров, которые я пробовал?
То же самое с параметрами. Вы можете использовать параметр в рекурсивном шаблоне/функции и обновлять его при каждом вызове, но я не думаю, что это подойдет для вашей ситуации.
На вашем месте я бы, наверное, сделал что-то вроде:
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, поскольку она включает количество?
Потому что я забыл его удалить. Посмотрите, подходит ли вам отредактированная версия.
это работает, но как я могу получить количество по его имени, поскольку поле количества продукта не всегда может отображаться как следующий брат или сестра, однако соглашение об именовании количества всегда будет именем продукта с суффиксом количества, например. productid-w-qty?
Определите ключ, соответствующий полю по имени, и используйте его, добавив суффикс "-qty" к имени продукта. --- П.С. Если у вас есть какой-либо контроль над форматом ввода, вы можете сэкономить много работы.
Я создал ключ для 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)">
?
Я думаю, что мы очень далеко отклонились от вашего первоначального вопроса. Я только хотел указать вам другое направление, а не писать весь код за вас. Если вы столкнулись с конкретной проблемой с реализацией, я предлагаю вам опубликовать отдельный вопрос, посвященный этой проблеме.
также у меня нет большого контроля над вводом, но я полагаю, что шаблоны можно было бы сократить до использования одного. Просто в некоторых формах есть поле qty, а в других нет, поэтому, если форма не включает qty, тогда qty можно принять равным 1. В этом случае мне нужно будет проверить тип формы, мне просто нужно выяснить, как использовать расчет цены * количества для поддержки обоих типов форм?
Переменные в XSLT неизменяемы. Вам нужно будет принять совершенно другой подход. Какую версию XSLT вы можете использовать?