2011-04-30 70 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

相关问题