2011-04-30 6 views
0

Je dispose d'une base de données dans Calc que je veux exporter au format XML à l'aide de filtres xslt. Les filtres fonctionnent correctement sauf lorsque les valeurs de deux colonnes adjacentes sont identiques. Par exemple, voir les données ci-dessous ...Bogue OpenOffice lors de l'exportation à partir de Calc à l'aide de filtres xslt

 
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 

Pour les données ci-dessus, cette erreur ne se produit que pour les lignes 3 et 5. Pour une raison quelconque, le filtre saute col4 et prend la valeur de Col5. Pour le reste des données, l'exportation fonctionne parfaitement. Voici le code 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> 

Quelqu'un peut-il donner des données à ce sujet? C'est assez bizarre et je suis vraiment coincé à cause de ça. Btw, j'utilise OpenOffice 3.1.1 (Build 9420) avec xslt 2.0.

Répondre

0

Le problème est dû à l'attribut number-columns-repeat de la table: élément de table-cellule dans la structure de données sous-jacente de la feuille. Pour plus de détails, veuillez vous référer à http://user.services.openoffice.org/en/forum/viewtopic.php?f=45&t=29674 et http://user.services.openoffice.org/en/forum/viewtopic.php?f=9&t=11865.

Bien que ce dernier lien affirme avoir résolu le problème, la solution n'est pas tout à fait ce que je cherchais. J'avais besoin d'une solution basée sur un index simple qui permette une génération de XML plus flexible. Voici ce que j'ai essayé de faire.

J'ai utilisé xslt 2.0 pour utiliser les fonctions définies par l'utilisateur. Voici la feuille de style ...

<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> 

Les balises utilisées ci-dessus ne sont que des espaces réservés. Veuillez les remplacer par ceux appropriés dans votre xslt. Cette solution est limitée par le nombre d'appels récursifs autorisés par le processeur xslt.

Si xslt 1.0 prend en charge l'envoi de nœud en tant que paramètres, nous pouvons essayer de remplacer le fichier udf ci-dessus pour obtenir une solution basée sur un modèle. Si vous trouvez des bugs, faites le moi savoir.

1

C'était génial code Rohit; ça m'a vraiment aidé à m'envoyer dans la bonne direction. J'avais du mal à faire fonctionner le code XSLT 2.0 dans mon installation LibreOffice, donc j'ai converti le code pour utiliser XSLT 1.0 (modèles nommés au lieu d'appels de fonctions, et une extension pour pouvoir passer un nœud dans la fonction récursive). Au cas où quelqu'un en aurait besoin, mon code est ci-dessous. Notez qu'il ne s'agit pas d'un code général - vous devrez remplacer mes champs par les vôtres.

Cet exemple particulier exporte une feuille de calcul dans un fichier .plist valide reconnu par XCode. Il a été testé avec LibreOffice 3.5 sous Vista.

<?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

Merci d'avoir posté le code. Aidera également si vous pouvez voter ma réponse si c'était utile :) –

Questions connexes