Jump to content

Accumulator in XSLT


netuh

Recommended Posts

Hi,This is my transformation...

<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><xsl:output method="xml" indent="yes"/><xsl:template match="/">	   <xsl:apply-templates/> </xsl:template><xsl:template match="/"><foo>   <xsl:attribute name="time">	  <xsl:for-each select="/things">		  <xsl:variable name="var1" select="position()" />		  <xsl:variable name="name" select="myName" />		  <moo>		  <xsl:for-each select="/othersThings">			  <xsl:variable name="var2" select="position()" />			  <xsl:if test="name = $name">				  <xsl:copy-of select="($var1+$var2)" />			  </xsl:if>		   </xsl:for-each>		   </moo>	   </xsl:for-each>   </xsl:attribute>   <xsl:attribute name="totalTime">	   <xsl:copy-of select=?????????? />   </xsl:attribute></foo>

My problem is, where the interrogations are, must be the sum of all moo's times, but i dont know how accumulate those values, once variables dont be changed... someone can help-me?sorry my poor English. :)

Link to comment
Share on other sites

I don't know how your input looks and I'm not sure I understand what you need, but I can already see some errors in your stylesheet that you need to fix.First, you don't need the:

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

Remove itAnd second, only absolute paths start with "/". So instead of using "/things" and "/othersThings", use "things" and "othersThings" instead (no slash at the beginning!).Last but not least, there should be spaces between variables, and instead of copy-of, you should use value-of, like this:

<xsl:value-of select="$var1 + $var2" />

Fix those, show some input and desired output and try to reformulate what you need.

Link to comment
Share on other sites

hi,i'm beginner in xslt, :) And the previous example is only to ilustrate the problem.in pseudo-code was be thus: :)

  int total = 0;  foreach A{	 foreach B{		 if (A.name == B.name){			total = total + A.position + B.position			value-of A.position + B.position		 }	 }  }  attribute time = total;

a example of my output is:

<performance-analysis>  <functional-component name="Functional Componente P" totaltime-requiredservices="2800">	<required-services>		<required-service name="salvar" time="300"/>		<required-service name="imprimir" time="400"/>		<required-service name="gerarRelatorio" time="200"/>		<required-service name="carregar" time="500"/>		<required-service name="validar" time="100"/>		<required-service name="exportar" time="400"/>		<required-service name="importar" time="600"/>		<required-service name="converter" time="300"/>	</required-services>   </functional-component></performance-analysis>

where the totaltime-requiredservices is the sum of required-service's time, and i only know this values when i generating the output. :) I hope clarified my situation. :blink:

Link to comment
Share on other sites

Fortunatly for you, XPath 1.0 has the sum() function which can sum the values from a certain node set.XSLT 1.0 however doesn't provide a straight way to convert a result tree fragment into a node-set (even though there are extensions for this).If your processor supports the EXSLT node-set extension or the MSXML node-set equivalent, the easiest way is this:

<xsl:stylesheet version="1.0"		  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"		  xmlns:exsl="http://exslt.org/common"		  extension-element-prefixes="exsl"><xsl:variable name="times"><!--whatever you do in order to generate this:		<required-service name="salvar" time="300"/>		<required-service name="imprimir" time="400"/>		<required-service name="gerarRelatorio" time="200"/>		<required-service name="carregar" time="500"/>		<required-service name="validar" time="100"/>		<required-service name="exportar" time="400"/>		<required-service name="importar" time="600"/>		<required-service name="converter" time="300"/>--></xsl:variable><xsl:template match="/"><performance-analysis>  <functional-component name="Functional Componente P" totaltime-requiredservices="{sum(exsl:node-set($times)/required-service/@time)}">	<xsl:copy-of select="exsl:node-set($times)"/>   </functional-component></performance-analysis></xsl:template></xsl:stylesheet>

Link to comment
Share on other sites

Thanks!!!!!!!i do a small change in your solution. I do two sequences transformations. The first create all nodes <required-service name="name" time="time"/> in a file auxiliary, and the another transfomation be a copy of this xml and sum all @time of <required-service name="name" time="time"/> to final xml.

<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><xsl:output method="xml" indent="yes"/><xsl:template match="/"><performance-analysis>	<xsl:for-each select="/performance-analysis/functional-component">		<functional-component>			<xsl:attribute name="name">					<xsl:value-of select="@name" />			  </xsl:attribute>			<xsl:attribute name="totaltime-requiredservices">					 <xsl:value-of select="sum(required-services/required-service/@time)" />			  </xsl:attribute>			<required-services>				<xsl:for-each select="required-services/required-service">					<required-service>					<xsl:attribute name="name">							<xsl:value-of select="@name" />					  </xsl:attribute>					<xsl:attribute name="time">							 <xsl:value-of select="@time" />					  </xsl:attribute>					</required-service>				</xsl:for-each>			</required-services>		</functional-component>	</xsl:for-each></performance-analysis></xsl:template></xsl:stylesheet>

Thanks again!!!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...