开发者

Removing elements based on child elements XSLT

I am new to Stack Overflow and to XSLT. I have a problem with removing duplicate entries from the output, based on some child element conditions.

Here is an example of XML that I have:

<partyorders>    
    <ord开发者_高级运维er>  
        <day>12</day>
        <month>05</month>  
        <year>2000</year>  
        <amount>5000.00</amount>  
        <decision>pending</decision>  
    </order>  
    <order>  
        <day>19</day>  
        <month>04</month>  
        <year>2000</year>  
        <amount>2000.00</amount>  
        <decision>pending</decision>  
    </order>  
    <order>  
        <day>19</day>  
        <month>04</month>  
        <year>2000</year>  
        <amount>2000.00</amount>  
        <decision>reserved</decision>  
    </order> 
     <order>  
        <day>05</day>  
        <month>04</month>  
        <year>2000</year>  
        <amount>1000.00</amount>  
        <decision>pending</decision>  
    </order>  
    <order>  
        <day>05</day>  
        <month>04</month>  
        <year>2000</year>  
        <amount>1000.00</amount>  
        <decision>reserved</decision>  
    </order> 
    <order>
        ....
    </order>
</partyorders>  

.... represents more orders of same as above

I need to get the output as:

  1. only one order with pending/approved status.
  2. if there are two orders with only different in status, i want to display reserved order only after confirming by comparing elements <day>, <month>, <year>, <amount>

I want the following output based on <day>, <month>, <year>, <amount> and <decision> tags:

<restrntpartyorders>    
    <restrntorder>  
        <partyday>12</partyday>
        <partymonth>05</partymonth>  
        <partyyear>2000</partyyear>  
        <partyamount>5000.00</partyamount>  
        <partydecision>pending</partydecision>  
    </restrntorder>  
    <restrntorder>  
        <partyday>19</partyday>  
        <partymonth>04</partymonth>  
        <partyyear>2000</partyyear>  
        <partyamount>2000.00</partyamount>  
        <partydecision>reserved</partydecision>  
    </restrntorder>  
    <restrntorder>  
        <partyday>05</partyday>  
        <partymonth>04</partymonth>  
        <partyyear>2000</partyyear>  
        <partyamount>1000.00</partyamount>  
        <partydecision>reserved</partydecision>  
    </restrntorder> 
    <restrntorder>
        ....
    </restrntorder>
</restrntpartyorders>  

Can someone help me out in getting the solution using XSLT 1.0?


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

  <!-- index order elements by year, month, day, amount -->
  <xsl:key 
    name="kOrdersByDate" 
    match="order" 
    use="concat(year, '-', month, '-', day, '$', amount)"
  />

  <xsl:template match="order">
    <!-- select all orders of same date and amount -->
    <xsl:variable name="same" select="
      key('kOrdersByDate', concat(year, '-', month, '-', day, '$', amount))
    " />
    <!-- of those, select the first 'reserved' order -->
    <xsl:variable name="same-reserved" select="
      $same[decision = 'reserved']
    " />

    <!-- check that either: 
      1. no other equal order, e.g. count($same) = 1, or
      2. reseverd order exists, take it
      3. no reseverd order exists, take the first "same" order
    -->
    <xsl:if test="
      count($same) = 1 
      or 
      ($same-reserved and generate-id() = generate-id($same-reserved[1]))
      or
      (not($same-reserved) and generate-id() = generate-id($same[1]))
    ">
      <!-- rename order -> restrntorder -->
      <restrntorder>
        <xsl:apply-templates select="*" />
      </restrntorder>
    </xsl:if>
  </xsl:template>

  <!-- rename partyorders -> restrntpartyorders -->
  <xsl:template match="partyorders">
    <restrntpartyorders>
      <xsl:apply-templates select="order" />
    </restrntpartyorders>
  </xsl:template>

  <!-- rename day etc. -> partyday etc. -->
  <xsl:template match="order/*">
    <xsl:element name="party{local-name()}">
      <xsl:value-of select="." />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

Output:

<?xml version="1.0" encoding="utf-8"?>
<restrntpartyorders>
    <restrntorder>
        <partyday>12</partyday>
        <partymonth>05</partymonth>
        <partyyear>2000</partyyear>
        <partyamount>5000.00</partyamount>
        <partydecision>pending</partydecision>
    </restrntorder>

    <restrntorder>
        <partyday>19</partyday>
        <partymonth>04</partymonth>
        <partyyear>2000</partyyear>
        <partyamount>2000.00</partyamount>
        <partydecision>reserved</partydecision>
    </restrntorder>

    <restrntorder>
        <partyday>05</partyday>
        <partymonth>04</partymonth>
        <partyyear>2000</partyyear>
        <partyamount>1000.00</partyamount>
        <partydecision>reserved</partydecision>
    </restrntorder>
    <restrntorder>
        ....
    </restrntorder>
</restrntpartyorders>


The relevant xsl:template contents would be:

<partyorders>
  <xsl:for-each select="/partyorders/order">
    <xsl:if test="count(following-sibling::order[day = current()/day and month = current()/month etc etc]) = 0">
      <xsl:copy-of select="." />
    </xsl:if>
  </xsl:for-each>
</partyorders>

It's O(N^2) tho, and I won't recommend using XSLT for that under load.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜