2013-03-28 26 views

回答

2

請注意,Joepie的回答引起溶液編譯時語法錯誤在任何符合標準的XSLT 1.0

SAXON 6.5.4 from Michael Kay 
Java version 1.6.0_31 
Error at xsl:value-of on line 11 of file:/(Untitled): 
    Error in expression      sum(hours/number(substring-before(., ':'))) +      sum(hours/number(substring-after(., ':'))) div 60     : Unexpected token [<function>] in path expression 
Transformation failed: Failed to compile stylesheet. 1 error detected. 
Press any key to continue . . . 

這裏是一個真正的工作,真X:處理器(它只能在不編譯錯誤若用XSLT 2.0處理程序執行) SLT 1.0溶液

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

<xsl:template match="/*"> 
    <xsl:copy> 
     <xsl:variable name="vrtfTimes"> 
     <xsl:for-each select="*"> 
      <t> 
       <xsl:value-of select= 
       "substring-before(., ':') + substring-after(.,':') div 60"/> 
      </t> 
     </xsl:for-each> 
     </xsl:variable> 
     <TotalHours> 
     <xsl:value-of select="floor(sum(ext:node-set($vrtfTimes)/*))"/> 
     </TotalHours> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔應用:

<Record> 
    <hours>10:30</hours> 
    <hours>20:30</hours> 
    <hours>10:60</hours> 
</Record> 

有用,正確的結果產生:

<Record> 
    <TotalHours>42</TotalHours> 
</Record> 

備註

如果你想獲得不僅從總和小時,還剩餘分鐘 - 爲分鐘:

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

<xsl:template match="/*"> 
    <xsl:copy> 
    <xsl:variable name="vrtfTimes"> 
     <xsl:for-each select="*"> 
     <t> 
      <xsl:value-of select= 
      "substring-before(., ':') + substring-after(.,':') div 60"/> 
     </t> 
     </xsl:for-each> 
    </xsl:variable> 

    <xsl:variable name="vSum" select="sum(ext:node-set($vrtfTimes)/*)"/> 
    <TotalHours> 
      <xsl:value-of select="floor($vSum)"/> 
      <xsl:text>:</xsl:text> 
      <xsl:value-of select="round(60* ($vSum - floor($vSum)))"/> 
    </TotalHours> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

當以下(稍微複雜)的XML應用這種轉變文檔:

<Record> 
    <hours>10:30</hours> 
    <hours>20:30</hours> 
    <hours>10:60</hours> 
    <hours>1:15</hours> 
    <hours>1:03</hours> 
</Record> 

正確的結果產生:

<Record> 
    <TotalHours>44:18</TotalHours> 
</Record> 
+0

嗨迪米特里,爲什麼說「這是一個真正可行的,真正的XSLT 1.0解決方案」。該解決方案使用默認變壓器中不可用的擴展?(您在功能xslt btw上工作的粉絲) – Joep

+0

@Joepie,歡迎使用XSLT 1.0 - xxx:node-set()擴展功能是事實上的標準,可以大量使用。大多數情況下,使用它的解決方案更高效且易於編寫。在這種特殊情況下,我故意選擇提供更高效的非遞歸解決方案。一個遞歸解決方案是可能的,它不使用任何擴展,但是當遞歸列表的長度通常在1000左右時,遞歸解決方案存在由於(實際)堆棧溢出導致的效率低下和崩潰的問題。我強烈建議避免遞歸只要有可能。 –

+0

@Joepie,我說「真正有效」,因爲與*你的*解決方案相反,這個解決方案使用XSLT 1.0處理器。 –

0

在XSLT 1.0:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output indent="yes"/> 

    <xsl:template match="Record"> 
     <Record> 
      <TotalHours> 
       <xsl:value-of select=" 
        sum(hours/number(substring-before(., ':'))) + 
        sum(hours/number(substring-after(., ':'))) div 60 
       "/> 
      </TotalHours> 
     </Record> 
    </xsl:template> 

</xsl:transform> 

Working example

如果你也想在一個小時的分數代替紀要:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output indent="yes"/> 

    <xsl:template match="Record"> 
     <Record> 
      <TotalHours> 
       <xsl:value-of select=" 
        concat(
         sum(hours/number(substring-before(., ':'))) + floor(sum(hours/number(substring-after(., ':'))) div 60), 
        '.', 
         format-number(floor(sum(hours/number(substring-after(., ':'))) mod 60), '00') 
        ) 
       "/> 
      </TotalHours> 
     </Record> 
    </xsl:template> 

</xsl:transform> 

** Working example

+0

Joepie,您在XSLT 1.0代碼中使用XPath 2.0語法 - 這隻能由XSLT 2.0處理器處理。請使用XSLT 1.0處理器運行此代碼以查看引發的語法錯誤。因此,按照OP的要求,這不是可用的XSLT 1.0解決方案。 –

相關問題