我有一个XML结构,如下所示:
<?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次的客户。
有可能吗?非常感谢!
答案 0 :(得分: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 < $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没有当前年份的概念 - 您必须使用扩展功能(取决于您的特定处理器支持的功能),或者在运行时将当前日期作为参数传递给样式表。
答案 1 :(得分: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 <= $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>
对于每个客户,这可以获得一年范围内不同旅行的次数(例如,对于三年范围,您需要三年不同,否则这意味着他们不会每年旅行)和每个不同的年份,它计算一年中旅行的次数,以满足要求。如果此类行程的总数等于所需的年数,则可以输出客户。