2011-04-30 57 views
0

我在Calc中有一個基於行的數據,我想使用xslt過濾器導出到xml。除非兩個相鄰列中的值相同,否則過濾器可以正常工作。例如,請參見下面的數據...從Calc使用xslt過濾器導出時出現OpenOffice錯誤

 
SrNo  Col2  Col3  Col4  Col5 
1   PQR  123  567  LMN 
2   OPQ  665  786  BCD 
3   EUR  443  443  UFF 
4   OLE  345  887  JAS 
5   EJR  565  565  OEP 

對於上述數據,只爲線3和5由於某種原因,發生該錯誤,所述過濾器將跳過COL4和從COL5取值。對於其他數據來說,導出完全正常。這裏是xslt代碼...

<row> 
<col1><xsl:value-of select="table:table-cell[1]"/></col1> 
<col2><xsl:value-of select="table:table-cell[2]"/></col2> 
<col3><xsl:value-of select="table:table-cell[3]"/></col3> 
<col4><xsl:value-of select="table:table-cell[4]"/></col4> 
<col5><xsl:value-of select="table:table-cell[5]"/></col5> 
</row> 

有人可以給任何輸入嗎?這很奇怪,而且由於這個原因我很困難。順便說一句,我使用xslt 2.0的OpenOffice 3.1.1(Build 9420)。

回答

0

問題出在表單的基礎數據結構中的number-columns-repeated屬性到table:table-cell元素。詳情請參閱http://user.services.openoffice.org/en/forum/viewtopic.php?f=45&t=29674http://user.services.openoffice.org/en/forum/viewtopic.php?f=9&t=11865

雖然後面的鏈接聲稱已經解決了這個問題,但解決方案並不完全符合我的要求。我需要一個簡單的基於索引的解決方案,它允許更靈活的xml代。這是我試圖解決的問題。

我已經使用xslt 2.0來使用用戶定義的函數。這裏是樣式表...

<xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="no"/> 

<xsl:function name="my:getColumnValue"> 
    <xsl:param name="tableRow" as="node()"/> 
    <xsl:param name="colIndex"/> 
    <xsl:param name="currentIndex"/> 
    <xsl:choose> 
     <xsl:when test="$currentIndex &lt; $colIndex"> 
      <xsl:variable name="repeatColumns" select="$tableRow/table:table-cell[$currentIndex]/@table:number-columns-repeated"/> 
      <xsl:choose> 
       <xsl:when test="$repeatColumns"> 
        <xsl:choose> 
         <xsl:when test="$currentIndex + $repeatColumns - 1 &gt;= $colIndex"><xsl:value-of select="$tableRow/table:table-cell[$currentIndex]"/></xsl:when> 
         <xsl:otherwise><xsl:value-of select="my:getColumnValue($tableRow, $colIndex - $repeatColumns + 1, $currentIndex + 1)"/></xsl:otherwise> 
        </xsl:choose> 
       </xsl:when> 
       <xsl:otherwise><xsl:value-of select="my:getColumnValue($tableRow, $colIndex, $currentIndex + 1)"/></xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise><xsl:value-of select="$tableRow/table:table-cell[$colIndex]"/></xsl:otherwise> 
    </xsl:choose> 
</xsl:function> 

<xsl:template match="//table:table"> 
    <Tests> 
     <!-- Process all table rows --> 
     <xsl:variable name="colCount" select="count(table:table-row[1]/table:table-cell)"/> 
     <xsl:for-each select="table:table-row"> 
      <xsl:if test="position() > 1"> 
      <Test> 
       <SrNo><xsl:value-of select="my:getColumnValue(.,1,1)"/></SrNo> 
       <Name><xsl:value-of select="my:getColumnValue(.,2,1)"/></Name> 
       <Age><xsl:value-of select="my:getColumnValue(.,3,1)"/></Age> 
       <Height><xsl:value-of select="my:getColumnValue(.,4,1)"/></Height> 
       <Address><xsl:value-of select="my:getColumnValue(.,5,1)"/></Address> 
      </Test> 
      </xsl:if> 
     </xsl:for-each> 
    </Tests> 
</xsl:template> 

上面使用的標籤是隻是佔位符。請用你的xslt中的適當的替換它們。該解決方案受到xslt處理器允許的遞歸調用次數的限制。

如果xslt 1.0支持以params的形式發送節點,那麼我們可以嘗試替換上述udf以獲得基於模板的解決方案。如果你發現任何錯誤,請讓我知道。

1

這是偉大的代碼Rohit;它肯定幫助我朝正確的方向發展。我很難得到在我的LibreOffice安裝中工作的XSLT 2.0代碼,因此我將代碼轉換爲使用XSLT 1.0(命名爲模板而不是函數調用,並且擴展能夠將節點傳遞給遞歸函數)。如果有人需要它,我的代碼在下面。請注意,它不是通用代碼 - 您需要用自己的代碼替換我的字段。

此特定示例將電子表格導出到由XCode識別的有效.plist文件。它已經在Vista上運行的LibreOffice 3.5進行了測試。

<?xml version="1.0" encoding="UTF-8"?> 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
    xmlns:xt="http://www.jclark.com/xt" 
    extension-element-prefixes="xt" 
    xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
    xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
    exclude-result-prefixes="office table text"> 

    <!--xsl:output method = "xml" indent = "yes" encoding = "UTF-8" omit-xml-declaration = "no"/--> 
    <xsl:output method = "xml" indent = "yes" encoding = "UTF-8" omit-xml-declaration = "no" doctype-system = "http://www.apple.com/DTDs/PropertyList-1.0.dtd" doctype-public = "-//Apple//DTD PLIST 1.0//EN" /> 

    <xsl:template name="getColumnValue"> 
     <xsl:param name="tableRow"/> 
     <xsl:param name="colIndex"/> 
     <xsl:param name="currentIndex"/> 
     <xsl:choose> 
      <xsl:when test="$currentIndex &lt; $colIndex"> 
       <xsl:variable name="repeatColumns" select="xt:node-set($tableRow)/table:table-cell[$currentIndex]/@table:number-columns-repeated"/> 
       <xsl:choose> 
        <xsl:when test="$repeatColumns"> 
         <xsl:choose> 
          <xsl:when test="$currentIndex + $repeatColumns - 1 &gt;= $colIndex"> 
           <xsl:value-of select="xt:node-set($tableRow)/table:table-cell[$currentIndex]"/> 
          </xsl:when> 
          <xsl:otherwise> 
           <xsl:variable name = "recursiveResult"> 
            <xsl:call-template name="getColumnValue"> 
             <xsl:with-param name="tableRow" select="$tableRow"/> 
             <xsl:with-param name="colIndex" select="$colIndex - $repeatColumns + 1"/> 
             <xsl:with-param name="currentIndex" select="$currentIndex + 1"/> 
            </xsl:call-template> 
           </xsl:variable> 
           <xsl:value-of select="$recursiveResult"/> 
          </xsl:otherwise> 
         </xsl:choose> 
        </xsl:when> 
        <xsl:otherwise> 
         <xsl:variable name = "recursiveResult"> 
          <xsl:call-template name="getColumnValue"> 
           <xsl:with-param name="tableRow" select="$tableRow"/> 
           <xsl:with-param name="colIndex" select="$colIndex"/> 
           <xsl:with-param name="currentIndex" select="$currentIndex + 1"/> 
          </xsl:call-template> 
         </xsl:variable> 
         <xsl:value-of select="$recursiveResult"/> 

        </xsl:otherwise> 
       </xsl:choose> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="xt:node-set($tableRow)/table:table-cell[$colIndex]"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <!-- By setting the PropertyValue "URL" in the properties used in storeToURL(), --> 
    <!-- we can pass a single parameter to this stylesheet.       --> 
    <!-- Caveat: If we use the "URL" property in the stylesheet and call in OOo  --> 
    <!-- from the menu "File" > "Export...", OOo assigns a target URL. And that  --> 
    <!-- might not be what we want.             --> 
    <xsl:param name="targetURL"/> 

    <xsl:variable name="exportDate"> 
     <xsl:choose> 
      <xsl:when test="string-length(substring-before($targetURL,';'))=10"> 
       <xsl:value-of select="substring-before($targetURL,';')"/> 
      </xsl:when> 
      <xsl:when test="string-length($targetURL)=10"> 
       <xsl:value-of select="$targetURL"/> 
      </xsl:when> 
     </xsl:choose> 
    </xsl:variable> 

    <xsl:variable name="exportUser"> 
     <xsl:if test="string-length(substring-after($targetURL,';'))>0"> 
      <xsl:value-of select="substring-after($targetURL,';')"/> 
     </xsl:if> 
    </xsl:variable> 

    <xsl:template match="/"> 
     <plist version="1.0"> 
      <dict> 
       <key>Animations</key> 
       <array> 
        <!-- Process all tables --> 
        <xsl:apply-templates select="//table:table"/> 
       </array> 
      </dict> 
     </plist> 
    </xsl:template> 


    <xsl:template match="table:table"> 
     <!-- Process all table-rows after the column labels in table-row 1 --> 
     <xsl:for-each select="table:table-row"> 
      <xsl:if test="position()>1"> 
       <dict> 
        <key>character</key> 
        <string> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="1"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </string> 

        <key>animation</key> 
        <string> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="2"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </string> 

        <key>cycle</key> 
        <xsl:variable name="cycleTmp"> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="3"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </xsl:variable> 
        <xsl:if test="$cycleTmp > 0"> 
         <true/> 
        </xsl:if> 
        <xsl:if test="$cycleTmp = 0"> 
         <false/> 
        </xsl:if> 

        <key>frames</key> 
        <integer> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="4"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </integer> 

        <key>randomSpeedPercent</key> 
        <integer> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="5"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </integer> 

        <key>spriteNameRoot</key> 
        <string> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="6"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </string> 

        <key>spriteSheetName</key> 
        <string> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="7"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </string> 

        <key>anchorX</key> 
        <integer> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="11"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </integer> 

        <key>anchorY</key> 
        <integer> 
         <xsl:call-template name="getColumnValue"> <xsl:with-param name="colIndex" select="12"/> <xsl:with-param name="currentIndex" select="1"/> <xsl:with-param name="tableRow" select="."/> </xsl:call-template> 
        </integer> 

       </dict> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 
+0

感謝您發佈代碼。如果你可以投我的答案,如果它是有用的,也將有所幫助:) – 2012-07-25 17:34:49

相關問題