问题描述:

I have a below XML structure and I want to sort the dates and update one date node to the latest date. Dates are in YYYY/mm/dd format. Below is the XML structure.

To be more specific I am putting an example below.

Let's say there are 3 Coverage Effective Dates 2015/01/01, 2015/01/02, 2015/01/03 then customerEffectiveDate should be updated to 2015/01/03.

Points to note about XML structure:

1. Product count can be from 1 to 10.

2. Coverage node can be from 1 to Many.

<Map>

<customer>

<customerDetails>

<!-- The customerEffectiveDate below should be updated to the latest among all the effectiveDate fron coverage.-->

<customerEffectiveDate>2014/06/02</customerEffectiveDate>

</customerDetails>

</customer>

<products>

<product1>

<!-- Coverage Nodes can occur multiple times. There is no limit.-->

<coverage>

<effectiveDate>2015/12/01</effectiveDate>

</coverage>

<coverage>

<effectiveDate>2015/11/01</effectiveDate>

</coverage>

</product1>

<product2>

<coverage>

<effectiveDate>2014/12/01</effectiveDate>

</coverage>

<coverage>

<effectiveDate>2015/09/01</effectiveDate>

</coverage>

</product2>

.

.

.

.

.

.

.

.

<product10></product10>

</products>

</Map>

Another point to note is I am using XSL 1.0. Can someone please help.

I have already looked at this, this and this.

Thanks.

网友答案:

Given that format you can easily sort it, write a template

<xsl:template match="customer/customerDetails/customerEffectiveDate">
  <xsl:copy>
    <xsl:for-each select="//coverage/effectiveDate">
      <xsl:sort select="." data-type="text" order="descending"/>
      <xsl:if test="position() = 1">
        <xsl:value-of select="."/>
      </xsl:if>
   </xsl:for-each>
 </xsl:copy>
</xsl:template>

plus the identity transformation template

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

to copy the rest unchanged.

网友答案:

This may not be the most simple way, but this approach sorts all <coverage> tags under the <product1-10> tags, extracts the latest value from all <effectiveDate> values and copies the rest.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>

<!-- Process <products> tag with higher priority, so that the follwing template does not match -->
<xsl:template match="products" priority="1">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="*[starts-with(local-name(),'product')]">
  <xsl:element name="{name()}">
    <xsl:for-each select="coverage">
      <xsl:sort select="effectiveDate/text()" order="descending" />
      <xsl:copy-of select="." />
    </xsl:for-each>
  </xsl:element>
</xsl:template>

<!-- extract the first 'effectiveDate' after sorting all values -->
<xsl:template match="customerEffectiveDate">
  <xsl:variable name="latest">
    <xsl:for-each select="../../../products//effectiveDate">
      <xsl:sort select="text()" order="descending" />
      <xsl:if test="position() = 1">
        <xsl:value-of select="." />
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <customerEffectiveDate><xsl:copy-of select="$latest" /></customerEffectiveDate>
</xsl:template>

</xsl:stylesheet>
相关阅读:
Top