2012-02-01 54 views
2

假设下面的XML输入...根据XSL中的条件动态输出元素?

<incidents> 
     <incident> 
       <year>2011</year> 
       <other data here> 
     </incident> 
     <incident> 
       <year>2009</year> 
       <other data here> 
     </incident> 
     <incident> 
       <year>2006</year> 
     </incident> 
</incidents> 

的XML总是逐年预先排序,以便最近发生的事件今年是第一次。我需要使用xsl来处理它,并且基本上以最少的转换输出数据,最多5年,但如果缺少任何年份,我只需要输出<incident><year>missingYear</year></incident>的元素。

因此,假设我有正确的XSL要做到这一点,处理上面的XML将产生此...

<incidents> 
    <incident> 
     <year>2011</year> 
    </incident> 
    <incident> 
     <year>2010</year> 
    </incident> 
    <incident> 
     <year>2009</year> 
    </incident> 
    <incident> 
     <year>2008</year> 
    </incident> 
    <incident> 
     <year>2007</year> 
    </incident> 
    <incident> 
     <year>2006</year> 
    </incident> 
</incidents> 

我能走到今天与XSL,但它不占之间较大的差距年

<xsl:variable name="maxYear" select="/incidents/incident/year[1]"></xsl:variable> 

<xsl:template match="incidents" > 
    <xsl:element name="incident">   
    <xsl:for-each select="incident">     
     <xsl:variable name="currentYear" select="year"/>    

     <xsl:choose> 
      <xsl:when test="($maxYear - (position() -1)) != $currentYear"> 
      <!-- output the missing year --> 
      <xsl:element name="year"> <xsl:value-of select="($maxYear - (position() -1))" /></xsl:element> 
      <!-- output the current year node --> 
      <xsl:element name="year"> <xsl:value-of select="$currentYear" /></xsl:element> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:element name="year"> <xsl:value-of select="$currentYear" /></xsl:element>    
      </xsl:otherwise>   
     </xsl:choose>      
    </xsl:for-each>  
    </xsl:element> 
</xsl:template> 

回答

1
如果你想生成的XML总是contaiin预测的元素(在这种情况下,连续多年,无间隙,即使源文件在几年的差距)

,那么你为什么不只是写它(生成的XML )?为什么要转换生成,如果你知道它需要什么?

我可能是夸张了一点:)

但这里有一个想法:选择最高和最低的年份值,或者第一和最后一个。然后将int值从一端循环到另一端。对于每个循环迭代,查找src xml中的匹配元素。如果找到,则生成其余部分,否则跳过。

+0

我已经更新了原来的问题,但现在回想起来,我认为你是对的....我可以得到当年的XSL,然后就回送从他们的5次,每次检查是否'year'在源xml中可用,如果没有,只需创建该元素。不知道为什么我让我的难度超过需求;感谢您的启发 – raffian 2012-02-01 02:01:32

2

I.下面是一个完整XSLT 1.0溶液

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

<xsl:param name="pYearsBack" select="6"/> 
<xsl:param name="pThisYear" select="2012"/> 

<xsl:variable name="vEarliest" select= 
    "$pThisYear - $pYearsBack"/> 

<xsl:variable name="vYears" select="/*/*/year"/> 

<xsl:template match="/"> 
    <incidents> 
    <xsl:call-template name="genYears"/> 
    </incidents> 
</xsl:template> 

<xsl:template name="genYears"> 
    <xsl:param name="pTimes" select="$pYearsBack+1"/> 
    <xsl:param name="pStart" select="$pThisYear"/> 

    <xsl:if test="$pTimes > 0"> 
    <incident> 
    <year> 
     <xsl:value-of select= 
     "concat($vYears[. = $pStart], 
       substring('missingYear', 
         1 div not($vYears[. = $pStart])) 
      ) 
     "/> 
    </year> 
    </incident> 

    <xsl:call-template name="genYears"> 
    <xsl:with-param name="pTimes" select="$pTimes -1"/> 
    <xsl:with-param name="pStart" select="$pStart -1"/> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

当这个变换所提供的XML文档施加(校正为良好的形成):

<incidents> 
    <incident> 
     <year>2011</year> 
     <other-data-here/> 
    </incident> 
    <incident> 
     <year>2009</year> 
     <other-data-here/> 
    </incident> 
    <incident> 
     <year>2006</year> 
    </incident> 
</incidents> 

想要的,正确的结果(全年事件从$pThisYear开始返回$pYearsBack年)产生

<incidents> 
    <incident> 
     <year>missingYear</year> 
    </incident> 
    <incident> 
     <year>2011</year> 
    </incident> 
    <incident> 
     <year>missingYear</year> 
    </incident> 
    <incident> 
     <year>2009</year> 
    </incident> 
    <incident> 
     <year>missingYear</year> 
    </incident> 
    <incident> 
     <year>missingYear</year> 
    </incident> 
    <incident> 
     <year>2006</year> 
    </incident> 
</incidents> 

II。 XSLT 2.0溶液

像往常一样,XSLT 2.0溶液更容易,更短,更readablr:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
exclude-result-prefixes="xs"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:param name="pYearsBack" select="6" as="xs:integer"/> 
<xsl:param name="pThisYear" select="2012" as="xs:integer"/> 

<xsl:variable name="vEarliest" select= 
    "$pThisYear - $pYearsBack -1"/> 

<xsl:variable name="vYears" select="/*/*/year/xs:integer(.)"/> 

<xsl:template match="/"> 
    <incidents> 
    <xsl:for-each select="1 to $pYearsBack +1"> 
    <xsl:variable name="vthisYear" as="xs:integer" 
     select="$pThisYear - . +1"/> 
    <incident> 
     <year> 
     <xsl:sequence select= 
     "($vYears[. eq $vthisYear], 'missingYear')[1]"/> 
     </year> 
    </incident> 
    </xsl:for-each> 
    </incidents> 
</xsl:template> 
</xsl:stylesheet> 

当该变换是在相同的XML文档(上文)中,相同的正确施加结果产生

<incidents> 
    <incident> 
     <year>missingYear</year> 
    </incident> 
    <incident> 
     <year>2011</year> 
    </incident> 
    <incident> 
     <year>missingYear</year> 
    </incident> 
    <incident> 
     <year>2009</year> 
    </incident> 
    <incident> 
     <year>missingYear</year> 
    </incident> 
    <incident> 
     <year>missingYear</year> 
    </incident> 
    <incident> 
     <year>2006</year> 
    </incident> 
</incidents> 
+0

感谢您的详细信息,这是伟大的见解,并将对我也有一些其他问题非常有帮助,再次感谢 – raffian 2012-02-01 16:25:07

+0

@RaffiM:不客气。 – 2012-02-01 17:03:52