2011-10-02 90 views
8

我对XSL和XML非常陌生,希望有一个简单的问题。我有一个XML文件,其中有两个数组,我需要总结。这里是XML文件的一部分总结两个数组中的XML数据

<?xml version="1.0" encoding="UTF-8"?> 
<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.44922</Intensity> 
        <Intensity>104.35479736328125</Intensity> 
        <Intensity>104.56911468505859</Intensity> 
        <Intensity>104.38999938964844</Intensity> 
        <Intensity>104.30992889404297</Intensity> 
        <Intensity>104.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> 

我真正想要的是来自两个Intensity数组的要素的总和加起来。因此,这将是这样的:

FirstArray [0] + SecondArray [0] =总和[0],这是真的

105.84667205810547 + 1.0229243040084839 = 106.8696 和

FirstArray [1] + SecondArray [1] =总和[1]

105.83854675292969+ 48.868541717529297 = 154.7071等等...

有在这两个,我需要忽略现在之间的一些其他物品。

谢谢!

回答

2

更新

sum功能,例如:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:key name="k" match="Intensity" use="count(preceding-sibling::Intensity)"/> 

    <xsl:template match="/"> 
    <root> 
     <xsl:apply-templates select="//Intensity[generate-id(.) = 
          generate-id(key('k', count(preceding-sibling::Intensity)))]"/> 
    </root> 
    </xsl:template> 

    <xsl:template match="Intensity"> 
    <sum> 
     <xsl:value-of select="sum(key('k', count(preceding-sibling::Intensity)))"/> 
    </sum> 
    </xsl:template> 

</xsl:stylesheet> 

这个模板总结两个IntensityArrayIntensity元素。

输出:

<root> 
    <sum>106.86959636211395</sum> 
    <sum>154.70708847045898</sum> 
    <sum>153.08208847045898</sum> 
    <sum>267.8320999145508</sum> 
    <sum>196.8874969482422</sum> 
    <sum>149.74459838867187</sum> 
    <sum>156.58208847045898</sum> 
    <sum>236.7624969482422</sum> 
    <sum>108.25000262260437</sum> 
    <sum>126.6500015258789</sum> 
    <sum>152.14999389648437</sum> 
    <sum>105.65709751844406</sum> 
    <sum>151.60709762573242</sum> 
    <sum>188.74459838867187</sum> 
    <sum>149.16250610351562</sum> 
    <sum>137.14999389648437</sum> 
    <sum>135.06958961486816</sum> 
    <sum>163.8374900817871</sum> 
    <sum>134.63208961486816</sum> 
    <sum>143.03750228881836</sum> 
    <sum>135.5749969482422</sum> 
    <sum>148.48750686645508</sum> 
    <sum>142.76250076293945</sum> 
    <sum>132.5749969482422</sum> 
    <sum>138.45709228515625</sum> 
    <sum>165.68749618530273</sum> 
    <sum>115.3000020980835</sum> 
    <sum>107.92500567436218</sum> 
    <sum>107.5500066280365</sum> 
</root> 
+0

基里尔喜 - 我想我并不清楚。我需要每个元素的总和,而不是整个数组。所以105.8466721 + 1.022924304然后105.8385468 + 48.86854172等... – user918967

+0

@ user918967,我已经更新了我的答案。 –

+0

@downvoter,小心点评? –

2

执行以下操作做你需要它?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

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

    <xsl:template match="ItemCollection"> 
    <xsl:variable name="itemCollection" select="." /> 
    <xsl:variable name="itemsCount" select="count((.//IntensityArray)[1]//Intensity)" /> 

    <xsl:for-each select="1 to $itemsCount"> 
     <xsl:variable name="itemIndex" select="." /> 
     <sum position="{$itemIndex}"> 
     <xsl:value-of select="sum($itemCollection//IntensityArray//Intensity[$itemIndex])" /> 
     </sum> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

我得到了下面的输出,当我跑在你的样本数据:

<root> 
    <sum position="1">106.86959636211395</sum> 
    <sum position="2">154.70708847045898</sum> 
    <sum position="3">153.08208847045898</sum> 
    <sum position="4">267.8320999145508</sum> 
    <sum position="5">196.8874969482422</sum> 
    <sum position="6">149.74459838867187</sum> 
    <sum position="7">156.58208847045898</sum> 
    <sum position="8">236.7624969482422</sum> 
    <sum position="9">108.25000262260437</sum> 
    <sum position="10">126.6500015258789</sum> 
    <sum position="11">152.14999389648437</sum> 
    <sum position="12">105.65709751844406</sum> 
    <sum position="13">151.60709762573242</sum> 
    <sum position="14">188.74459838867187</sum> 
    <sum position="15">149.16250610351562</sum> 
    <sum position="16">137.14999389648437</sum> 
    <sum position="17">135.06958961486816</sum> 
    <sum position="18">163.8374900817871</sum> 
    <sum position="19">134.63208961486816</sum> 
    <sum position="20">143.03750228881836</sum> 
    <sum position="21">135.5749969482422</sum> 
    <sum position="22">148.48750686645508</sum> 
    <sum position="23">142.76250076293945</sum> 
    <sum position="24">132.5749969482422</sum> 
    <sum position="25">138.45709228515625</sum> 
    <sum position="26">165.68749618530273</sum> 
    <sum position="27">115.3000020980835</sum> 
    <sum position="28">107.92500567436218</sum> 
    <sum position="29">107.5500066280365</sum> 
</root> 
+0

Hi Luke,在EditX 2010中运行您的代码我在表达式1中获得以下错误$ itemsCount:意外的令牌超出表达式 – user918967

+0

奇怪的是,它在撒克逊的工作很好。由于EditiX 2010明显支持XPath 2.0,如果将''元素的'version'属性更改为'2.0',会有帮助吗? –

+0

嗨卢克 - 是的伎俩! – user918967

1

这种转变产生想要的结果,即使在珊瑚礁两个节点集有不同数量的节点和/或一些在第二节点集合中的节点的不具有值,该值是可浇注到一个号码

<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> 

当t他的转换应用于以下XML文档(与提供的相同,但添加到第一个节点集多一个Intensity元素(最后一个),以使这两个节点集的大小不同):

<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.44922</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> 

想要的,正确的结果产生

<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> 

说明

  1. 定义了两个变量,每个变量都包含编译“数组”的节点。

  2. 定义了另外两个变量:$vShorterArr,包含较短的节点集和$vLongerArr包含较长的节点集。

  3. 模板适用于较长的节点集。

  4. 较长节点集合中的每个节点与较短节点集合中相应(如果存在)节点相加,或与0相加,否则为0。

二, XSLT 2.0溶液

<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。使用FXSL

这是很容易使用的FXSLf:zip-with()功能/模板来解决这个问题。

下面是一个使用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"/> 

    <!-- To be applied on numList.xml --> 
    <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> 
+0

我真正的XML文档比较复杂。有几个运行产生我需要总结的数组对。所有这些都可以嵌套在for-each循环中吗? – user918967

+0

@ user918967:不需要'xsl:for-each'只是推动你的函数'zip-with()',或者使用FXSL提供的函数。 –

+0

我正在查看代码,Dimitre我认为你更容易使用,当我正在寻找一对称为Item name =“BaseLineOffSet”和Item name =“DispIntervalsMaxValues”的Intensity数组并忽略所有Intensity数组时。 Dmimitre,我将如何修改变量以仅获取这两个数组? – user918967