2009-12-15 77 views
0

我是Stack Overflow和XSLT的新手。基于某些子元素条件,从输出中删除重复条目时遇到问题。删除基于子元素的元素XSLT

这里是XML的一个例子,我有:

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

....代表相同的多个订单如上

我需要输出为:

  1. 只有一个订单具有待决/批准状态。
  2. 如果有两个订单仅在状态不同,我想仅通过比较元素<day><month><year>确认后显示保留的顺序,<amount>

我想根据<day>以下输出,<month><year><amount><decision>标签:

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

有人能帮助我在获得使用XSLT 1.0解决?

回答

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

输出:

<?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> 
+0

谢谢Tomalak。我有问题1.如果我想过滤拒绝状态的订单,该怎么办? 2.如果我需要定制outpout..ie,输出元素可以是而不是而不是。请帮忙 – angi 2009-12-16 20:51:12

0

相关的xsl:模板内容将是:

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

这是O(N^2)寿,我不会建议使用XSLT用于在负载下。

+0

你当然可以使用XSLT为。你不能使用* that * XSLT。 Tomalak的答案所采用的Muenchian技术是O(N)。 – 2009-12-16 17:00:28

+0

你很可能是对的。 – alamar 2009-12-18 10:40:28