This conversion leads to the desired result even in the case when two node-sets have a different number of nodes and / or some of the nodes in the second node-set do not have a value that can be changed to a number :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:variable name="vArr1" select= "/*/*/*/Item[1]/*/IntensityArray/*"/> <xsl:variable name="vArr2" select= "/*/*/*/Item[2]/*/IntensityArray/*"/> <xsl:variable name="vShorterArr" select= "$vArr1[not(count($vArr1) > count($vArr2))] | $vArr2[not(count($vArr2) >= count($vArr1))] "/> <xsl:variable name="vLongerArr" select= "$vArr2[not(count($vArr1) > count($vArr2))] | $vArr1[not(count($vArr2) >= count($vArr1))] "/> <xsl:template match="/"> <summedIntensities> <xsl:apply-templates select="$vLongerArr"/> </summedIntensities> </xsl:template> <xsl:template match="Intensity"> <xsl:variable name="vPos" select="position()"/> <Intensity> <xsl:variable name="vVal2" select="$vShorterArr[position()=$vPos]"/> <xsl:value-of select= ". + concat('0', substring($vVal2, 1 div (number($vVal2) = number($vVal2)) ) ) "/> </Intensity> </xsl:template> </xsl:stylesheet>
when this conversion is applied to the following XML document (similar to the one provided, but added to the first node-set, another Intensity element (last) to make the two node-sets different in size):
<out_xml> <Root> <ItemCollection> <Item name="BaseLineOffSet" type="2"> <Histogram> <DispOrder>This is Order</DispOrder> <IntensityArray> <Intensity>105.84667205810547</Intensity> <Intensity>105.83854675292969</Intensity> <Intensity>105.57729339599609</Intensity> <Intensity>105.66104888916016</Intensity> <Intensity>105.56392669677734</Intensity> <Intensity>105.33917236328125</Intensity> <Intensity>105.33854675292969</Intensity> <Intensity>105.31544494628906</Intensity> <Intensity>105.40036010742187</Intensity> <Intensity>105.21470642089844</Intensity> <Intensity>105.14356994628906</Intensity> <Intensity>104.92792510986328</Intensity> <Intensity>104.93791961669922</Intensity> <Intensity>104.93979644775391</Intensity> <Intensity>104.96470642089844</Intensity> <Intensity>105.01107025146484</Intensity> <Intensity>104.76479339599609</Intensity> <Intensity>104.9085693359375</Intensity> <Intensity>104.70166778564453</Intensity> <Intensity>104.75499725341797</Intensity> <Intensity>104.77352905273437</Intensity> <Intensity>104.77714538574219</Intensity> <Intensity>104.59485626220703</Intensity> <Intensity>104.73235321044922</Intensity> <Intensity>104.35479736328125</Intensity> <Intensity>104.56911468505859</Intensity> <Intensity>104.38999938964844</Intensity> <Intensity>104.30992889404297</Intensity> <Intensity>104.37964630126953</Intensity> <Intensity>105.37964630126953</Intensity> </IntensityArray> </Histogram> </Item> <Item name="DispIntervalsMaxValues" type="2"> <Histogram> <DispOrder>This is Order</DispOrder> <IntensityArray> <Intensity>1.0229243040084839</Intensity> <Intensity>48.868541717529297</Intensity> <Intensity>47.504795074462891</Intensity> <Intensity>162.17105102539062</Intensity> <Intensity>91.323570251464844</Intensity> <Intensity>44.405426025390625</Intensity> <Intensity>51.243541717529297</Intensity> <Intensity>131.44705200195312</Intensity> <Intensity>2.8496425151824951</Intensity> <Intensity>21.435295104980469</Intensity> <Intensity>47.006423950195312</Intensity> <Intensity>0.72917240858078003</Intensity> <Intensity>46.669178009033203</Intensity> <Intensity>83.804801940917969</Intensity> <Intensity>44.197799682617187</Intensity> <Intensity>32.138923645019531</Intensity> <Intensity>30.30479621887207</Intensity> <Intensity>58.928920745849609</Intensity> <Intensity>29.930421829223633</Intensity> <Intensity>38.282505035400391</Intensity> <Intensity>30.801467895507813</Intensity> <Intensity>43.710361480712891</Intensity> <Intensity>38.167644500732422</Intensity> <Intensity>27.842643737792969</Intensity> <Intensity>34.102294921875</Intensity> <Intensity>61.118381500244141</Intensity> <Intensity>10.910002708435059</Intensity> <Intensity>3.6150767803192139</Intensity> <Intensity>3.1703603267669678</Intensity> </IntensityArray> </Histogram> </Item> </ItemCollection> </Root> </out_xml>
required, the correct result is obtained :
<summedIntensisites> <Intensity>106.86959636211395</Intensity> <Intensity>154.70708847045898</Intensity> <Intensity>153.08208847045898</Intensity> <Intensity>267.8320999145508</Intensity> <Intensity>196.8874969482422</Intensity> <Intensity>149.74459838867188</Intensity> <Intensity>156.58208847045898</Intensity> <Intensity>236.7624969482422</Intensity> <Intensity>108.25000262260437</Intensity> <Intensity>126.6500015258789</Intensity> <Intensity>152.14999389648438</Intensity> <Intensity>105.65709751844406</Intensity> <Intensity>151.60709762573242</Intensity> <Intensity>188.74459838867188</Intensity> <Intensity>149.16250610351562</Intensity> <Intensity>137.14999389648438</Intensity> <Intensity>135.06958961486816</Intensity> <Intensity>163.8374900817871</Intensity> <Intensity>134.63208961486816</Intensity> <Intensity>143.03750228881836</Intensity> <Intensity>135.5749969482422</Intensity> <Intensity>148.48750686645508</Intensity> <Intensity>142.76250076293945</Intensity> <Intensity>132.5749969482422</Intensity> <Intensity>138.45709228515625</Intensity> <Intensity>165.68749618530273</Intensity> <Intensity>115.3000020980835</Intensity> <Intensity>107.92500567436218</Intensity> <Intensity>107.5500066280365</Intensity> <Intensity>105.37964630126953</Intensity> </summedIntensisites>
Explanation
Two variables are defined, each of which contains nodes that contain an "array".
Two other variables are $vShorterArr : $vShorterArr containing a shorter node -set and $vLongerArr containing a longer node -set.
Patterns apply to a longer node-set.
Each node in the longer node-set is summed with the corresponding (if any) node in the shorter node-set or with 0 otherwise.
II. XSLT 2.0 Solution :
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:variable name="vArr1" select= "/*/*/*/Item[1]/*/IntensityArray/*/number()"/> <xsl:variable name="vArr2" select= "/*/*/*/Item[2]/*/IntensityArray/*/number()"/> <xsl:variable name="vShorterArr" select= "if(count($vArr1) lt count($vArr2)) then $vArr1 else $vArr2 "/> <xsl:variable name="vLongerArr" select= "if(count($vArr1) ge count($vArr2)) then $vArr1 else $vArr2 "/> <xsl:template match="/"> <summedIntensities> <xsl:for-each select="$vLongerArr"> <xsl:variable name="vPos" select="position()"/> <Intensity> <xsl:variable name="vVal2" select= "$vShorterArr[$vPos]"/> <xsl:sequence select= ". + (if($vVal2 castable as xs:double) then $vVal2 else 0 ) "/> </Intensity> </xsl:for-each> </summedIntensities> </xsl:template> </xsl:stylesheet>
III. Using FXSL :
It is much easier to solve this problem using f:zip-with() function / template FXSL .
The following is a solution using FXSL 2 :
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://fxsl.sf.net/" exclude-result-prefixes="f" > <xsl:import href="../f/func-zipWithDVC.xsl"/> <xsl:import href="../f/func-Operators.xsl"/> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="/"> <summedIntensities> <xsl:for-each select= "f:zipWith(f:add(), /*/*/*/Item[1]/*/IntensityArray/*/number(), /*/*/*/Item[2]/*/IntensityArray/*/number() )" > <Intensity> <xsl:sequence select="."/> </Intensity> </xsl:for-each> </summedIntensities> </xsl:template> </xsl:stylesheet>
Dimitre novatchev
source share