2016-02-21 61 views
1

我有一个XML结构,它看起来像这样:XSL复杂的选择条件

<?xml version="1.0" encoding="UTF-8"?> 
<Customers> 
    <Customer UD="XYZ"> 
     <Info> 
       ... 
      </Info> 
      <Travel> 
       <Trip Country="US" Year="2013" LengthOfStay="P13D"/> 
       <Trip Country="IT" Year="2015" LengthOfStay="P9D"/> 
       <Trip Country="JP" Year="2015" LengthOfStay="P5D"/> 
      </Travel> 
     </Customer> 
     <Customer UD="ABC"> 
      ... 
     </Customer> 
</Customers> 

我想创建一个复杂的选择条件,返回行驶超过的时代,每年量X客户过去X年。

会有可能吗?非常感谢!

+1

** 1。** XML中只有一个客户。 - ** 2。**“最近X年每年X次以上”的条件含糊不清:这可能意味着在过去Y年的每一次**中X次以上,或者在过去的Y年中平均每年**超过X次**。 –

+0

同意,XML中只有一个客户,但在根元素下会有更多。我希望得到在过去的Y年中一次旅行超过X次的客户。希望它现在更有意义。提前谢谢你的帮助。 – user2135025

回答

1

有可能在我的逻辑瑕疵的地方,但试试这个XSLT

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

    <xsl:param name="firstYear" select="2012" /> 
    <xsl:param name="lastYear" select="2015" /> 
    <xsl:param name="times" select="2" /> 

    <xsl:variable name="Years" select="$lastYear - $firstYear + 1" /> 

    <xsl:key name="Trip" match="Trip" use="concat(@Year, '|', ../../@UD)" /> 

    <xsl:template match="Customers"> 
     <xsl:copy> 
      <xsl:apply-templates select="Customer[count(.//Trip 
           [@Year >= $firstYear and @Year &lt;= $lastYear] 
           [generate-id() = generate-id(key('Trip', concat(@Year, '|', ../../@UD))[1])] 
           [count(key('Trip', concat(@Year, '|', ../../@UD))) >= $times] 
          ) = $Years]" /> 
     </xsl:copy> 
    </xsl:template> 

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

对每一个客户,这得到了一年的范围之间不同的出行次数,(所以对于一个为期三年的范围,例如,那么你需要三个不同的年份,否则这意味着他们每年都没有旅行),并且每个不同的年份都计算他们在一年中旅行的次数,以确保它符合要求。如果此类行程的总次数等于所需的年数,则可输出该客户。

+0

这真是太神奇了,谢谢你们! – user2135025

+0

做得很好+1。 –

1

我不认为这是可能的直接选择的符合条件的客户,但你可以使用递归模板来处理客户和输出结果,只有当他们通过测试。

下面是一个例子:

XSLT 1.0

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

<xsl:key name="trip" match="Trip" use="concat(@Year, '|', ../../@UD)" /> 

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

<xsl:template match="Customer"> 
    <xsl:call-template name="test-years"/> 
</xsl:template> 

<xsl:template name="test-years"> 
    <xsl:param name="year" select="2016"/> 
    <xsl:param name="years-to-test" select="3"/> 
    <xsl:param name="min-trips" select="3"/> 
    <xsl:variable name="n" select="count(key('trip', concat($year, '|', @UD)))" /> 
    <xsl:choose> 
     <xsl:when test="$n &lt; $min-trips"> 
      <!-- exit with no result --> 
     </xsl:when> 
     <xsl:when test="$years-to-test > 1"> 
      <!-- recursive call --> 
      <xsl:call-template name="test-years"> 
       <xsl:with-param name="year" select="$year - 1"/> 
       <xsl:with-param name="years-to-test" select="$years-to-test - 1"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
      <!-- test passed: output the result --> 
      <xsl:copy-of select="."/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 

注:XSLT 1.0已经没有当年的概念 - 您必须使用了扩展功能(取决于你的特定处理器支持) ,或者在运行时将当前日期作为参数传递给样式表。