2012-02-01 42 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