подсчет суммы произведения элементов

jer

...
подсчет суммы произведения элементов

есть корзина с товарами:

<basket>
<prod id="1">
<name>aaa</name>
<price>10</price>
<quantity>3</quantity>
</prod>
<prod id="2">
<name>bbb</name>
<price>20</price>
<quantity>5</quantity>
</prod>
<prod id="3">
<name>ccc</name>
<price>33</price>
<quantity>2</quantity>
</prod>
</basket>

нужно посчитать полную стоимость корзины.
количество товаров в корзине считается:

<xsl:value-of select="sum(//prod/quantity)"/>

,а как посчитать полную стоимость корзины?
с sum() что-то не получается ;(((
 

sokov

Guest
Re: подсчет суммы произведения элементов

XSLT Вам этого не подсчитает, потому что он узлами манипулировать должен, а не арифметикой заниматья.
Я вижу 2 способа, как это можно провернуть.
* Самое реальное - это через JavaScript - расширение, которое поддерживается процессором Sablotron, после особой хитрой компиляции. Работает только под Perl. Я компилял под FreeBSD 4.х, могу поделиться бинарями, если что.
* Есть ещё какой-то хитрый процессор, который как раз под что-то подобное писали, то ли SAT, то ли SALT - могу посмотреть поточнее, если первое не подойдёт.

Если решишься - с доками помогу дальше.
 

slach

Новичок
а я вижу что надо не тупить а просто добавить это самое ПРОИЗВЕДЕНИЕ в XML Файл

что нить типа
<basket summa="145.00" currency="USD">

потому что ДАННЫЕ должны ВСЕ загоняться в XML...

XSLT не предназначен для вычислений или построений графиков... не надо заставлять его делать то, для чего он не предназначен
 

jer

...
ну он узлами и манипулирует, только нужно применить наипростейшие арифметические действия. у меня такое ощущение что это реализуемо на xslt, уверен что с помощью рекурсии через call-template это точно можно сделать, но кажется что можно и проще.

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

народ, есть еще мнения?
 

chameleon

Новичок
XSLT не предназначен для вычислений
а зря :).. где-то видел шаблон, позволяющий умножать (читай рекурсивно прибавлять) два переданных параметра и тот под saxon...
потому что ДАННЫЕ должны ВСЕ загоняться в XML...
имхо, возникает первоначальное впечатление, что эти данные избыточны, вот человек и задал вопрос.
 

jer

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

хотя я уже чую что если не получится на xslt это просто посчитать, то придется в xml пихать ;)
 

slach

Новичок
такс, я смотрю голос разума вы услышать не в состоянии...

рекурсия будет работать, я так даже делал, только подумай КАКОЙ будет overhead ... в чем смысл введения туевой хучи кода, для подсчета всего одной цифири??

что трудно вынести это число в XML ???
 

jian

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

 <xsl:output method="xml" encoding="UTF-8" />

 <xsl:template match="/">
  <xsl:variable name="comma_separated_data">
   <xsl:apply-templates select="basket/prod"/>
  </xsl:variable>

  <xsl:variable name="total_price">
    <xsl:call-template name="gimme_the_sum">
     <xsl:with-param name="comma_separated_data" select="$comma_separated_data"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="$total_price"/>

 </xsl:template>

<xsl:template match="prod">
 <xsl:value-of select="price*quantity"/>,<xsl:text/>
</xsl:template>

 <xsl:template name="gimme_the_sum">
  <xsl:param name="comma_separated_data"/>
  <xsl:param name="sum" select="0"/>
  <xsl:choose>
  <xsl:when test="substring-before($comma_separated_data,',')">
   <xsl:call-template name="gimme_the_sum">
    <xsl:with-param name="comma_separated_data" select="substring-after($comma_separated_data,',')"/>
    <xsl:with-param name="sum" select="$sum+substring-before($comma_separated_data,',')"/>
   </xsl:call-template>
  </xsl:when>
  <xsl:otherwise>
   <xsl:value-of select="$sum"/>
  </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

</xsl:stylesheet>

cheers
 

chameleon

Новичок
короче вот.
2slaсh: не думаю что это много кода...
PHP:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
		<xsl:call-template name="summ_price">
			<xsl:with-param name="prods" select="/basket/prod"/>
		</xsl:call-template>
	</xsl:template>
	<xsl:template match="prod" mode="summary">
			<xsl:value-of select="price * quantity"/>
	</xsl:template>
	<xsl:template name="summ_price">
		<xsl:param name="prods"/>
		<xsl:choose>
			<xsl:when test="$prods">
				<xsl:variable name="first">
					<xsl:apply-templates select="$prods[1]" mode="summary"/>
				</xsl:variable>
				<xsl:variable name="other">
					<xsl:call-template name="summ_price">
						<xsl:with-param name="prods" select="$prods[position()!=1]"/>
					</xsl:call-template>
				</xsl:variable>
				<xsl:value-of select="$first + $other"/>
			</xsl:when>
			<xsl:otherwise>0</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
</xsl:stylesheet>
код конечно побился - обработать напильником :)
 

Sababa

Guest
не надо изобретать велосипед:

http://topxml.com/xsl/articles/recurse/

Если ты формируешь xml сам, то я бы послушал slach-а и добавил еще один элемент с общей суммой (не потому, что xslt не может этого сделать, а потому, что сможешь выиграть в скорости). А вот если ты хранишь данные в xml-е или получаешь их из базы уже в xml виде, то считай в xslt и не парься, на сколько я понимаю, корзина покупателя редко когда будет превышать 3-5 единиц, а это не смертельно.
 

sokov

Guest
Автор оригинала: jer
я понимаю что считать интегралы в xslt не получится, но простые арифметические действия то почему бы и нет?
Вот в том-то весь и прикол, что интегралы - получится, а эту элементарную задачу придётся решать через пень-колоду. Такой вот он, наш XSL...

Кстати, я ещё слышал, что некоторые процессоры (Xalan, по-моему) отклоняются от спецификации и позволяют переопределять значения переменных в листе стилей. Можешь на этом сыграть. В ущерб переносимости, конечно.
 

jer

...
пока останавлюсь на варианте xslt, но если будет тормозить буду считать в xml-е.
(просто формирование xml может происходить и без моего ведома ;)

пасибо за участие в дискуссии...
 

[DAN]

Старожил PHPClub
Не вижу повода для дискурса.
В XSLT 2 значения переменных в шаблоне могут переопределяться ;)
 

chameleon

Новичок
ИМХО: если функции расширения так востребованы в данный момент, то чисто функциональным языком у xslt остаться врядли получится...
интересно услышать другие мнения.
 

sokov

Guest
тут я согласен полностью. И считаю, что это есть гут!!! Низкий поклон тем, кто на голом энтузиазме колбасит exslt.
 

Андрей М.

Guest
sokov:
в пхп тоже можно скомпилить саблотрон с js (--with-sablot-js), судя по мануалу, я не пробовал... или не будет работать?

--
На самом деле в большинстве случаев вполне достаточно xsl:script который есть в стандарте XSLT 1.1, совсем необязательно ждать 2.0. Жду-недождусь, когда libxml будет его поддерживать :) (Саблотроном я не пользуюсь)

Еще есть мнение, что чем сложнее будет XSLT тем больше времени будет уходить на его разбор и выполнение преобразований.

я тут подумал, через некоторое время народ начнет требовать что-то типа
PHP:
<xsl:class name="myclass">
   <xsl: property name="prop" public="true" static="true">
    ....
</xsl:class>
:))

Совсем офф: в недрах W3C сейчас зреет еще одна штука: XML Query, думаю, когда это можно будет использовать, XSLT будет выглядеть вообще тяжелым и неповоротливым инструментом. Вот примерчик с w3.org:
PHP:
<bib>
 {
  for $b in doc("http://www.bn.com/bib.xml")/bib/book
  where $b/publisher = "Addison-Wesley" and $b/@year > 1991
  return
    <book year="{ $b/@year }">
     { $b/title }
    </book>
 }
</bib>
т.е. итоговый документ просто программируется!:)
 

sokov

Guest
в пхп тоже можно скомпилить саблотрон с js (--with-sablot-js), судя по мануалу, я не пробовал... или не будет работать?
Да будет конечно, я не пробовал просто: на платном хостинге сижу - до расширений php не добраться, а вот собственноручно скомпилённый перловый модуль подрубить - не вопрос! Частенько этим балуюсь...

Жду-недождусь, когда libxml будет его поддерживать :)
Если так - то это хорошая новость!!!!

Да вот, прочитал всё это и впал в глубокую задумчивость...
 

Sababa

Guest
To Андрей:

Не путайте, пжлст, XML Query Language c XSLT, это совсем разные вещи. А то вот народ уже начали пугать.
 
Сверху