xsl merge elements and sort by 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">
精彩评论