开发者

xsl merge elements and sort by date

开发者 https://www.devze.com 2023-01-11 06:39 出处:网络
I have the following xml <Values> <New> <value>110</value> <date>2009-10-15</date>

I have the following xml

<Values>
 <New>
    <value>110</value>
    <date>2009-10-15</date>
  </New>
  <Previous>
    <value>100</value>
    <date>2010-10-15</date>
  </Previous>
  <Previous>
    <value>130</value>
    <date>2008-10-15</date>
  </Previous>
</Values>

I am using the following xsl

 <xsl:variable name="mergedData">
       <xsl:for-each select="//Values/New">
             <xsl:copy-of select="."/>
       </xsl:for-each>
       <xsl:for-each select="//Values/Previous">
             <xsl:copy-of select="."/>
       </xsl:for-each>
    </xsl:variable>


<xsl:for-each select="msxsl:node-set($mergedData)">
     <xsl:sort order="descending" select="substring(date,1,4)"/>
     <xsl:sort order="descending" select="substring(date,6,2)"/>
     <xsl:sort order="descending" select="substring(date,9,2)"/>
         <xsl:if test="position()=1">
              <xsl:value-of select="."/>
 开发者_开发百科         </xsl:if>
</xsl:for-each>

And I get the following.

110 2009-10-15 100 2010-10-15 130 2008-10-15

It does no seems to sort by date and its giving me back a lump of code I need to be sorted by date and been able to manipulate data so I can put them in table rows.

Like this.

110 2009-10-15 
100 2010-10-15 
130 2008-10-15


It does no seems to sort by date and its giving me back a lump of code I need to be sorted by date and been able to manipulate data so I can put them in table rows.

Like this.

110 2009-10-15  
100 2010-10-15  
130 2008-10-15

No, the code (if it were correct) would output the string value of one of the New or Previous elements with maximum date.

Here is the main problem in your code:

<xsl:for-each select="msxsl:node-set($mergedData)"> 

the msxsl:node-set() extension function returns a document tree -- not a top element or an XML fragment. To put it in other words, it returns the root node: / of this document tree.

Therefore, the <xsl:for-each> above selects a single node only, and this node has children that are only New or Previous elements. Therefore, there is no sort, because the result of sorting a single node is always this same node.

Then later in the code:

<xsl:value-of select="."/>

Because . is the root node of the temporary tree, the above xslt instruction produces the string value of the whole temporary tree -- that is, the concatenation, in document order, of all text nodes in this temporary tree. This is exactly what you complain of getting.

Solution:

Replace:

<xsl:for-each select="msxsl:node-set($mergedData)"> 

with:

<xsl:for-each select="msxsl:node-set($mergedData)/*"> 

Now, the select attribute of xsl:for-each selects all New and Previous top elements in the tree, as obviously was desired.


 <xsl:sort order="descending" select="substring(date,1,4)"/>
 <xsl:sort order="descending" select="substring(date,6,2)"/>
 <xsl:sort order="descending" select="substring(date,9,2)"/>

XML is case-sensitive. the reference to "date" needs to match the case of the input XML

Note: I assume that this

<xsl:variable name=">

is a typo and you meant

<xsl:variable name="mergedData">
0

精彩评论

暂无评论...
验证码 换一张
取 消