Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2008
    Messaggi
    18

    [xsl] Ricerca note in .docx, problema with-param

    Ciao a tutti,

    Sul blog di Harri Kiiskinen è presente un codice xslt per passare da docx (document.xml contenuto in tutti i file .docx) a latex. Minimale ma funzionale.

    C'è solo un problema, nel processare le note a piè di pagina il codice restituisce sempre e solo il testo relativo alla nota numero 1. Cerco di spiegare il problema:

    La struttura delle note all'interno del testo in document.xml in docx è, MOLTO in sintesi, la seguente:

    codice:
    <w:document>
      <w:body>
         <w:p>
           <w:r>
             <w:footnoteReference w:id="n" />
           </w:r>
          
           <w:r>
              <w:footnoteReference w:id="n+1" />
           </w:r>
          ......
         </w:p>
       </w:body>
    </w:document>
    Il testo delle note è presente in un secondo file, footnotes.xml, in questo modo:

    codice:
    <w:footnotes>
      <w:footnote w:id="n">
        <w:p>
          <w:r>
            <w:t>
              Testo della nota
            </w:t>
           </w:r>
         </w:p>
       </w:footnote>
        ....
    </w:footnotes>
    Ed ecco come il codice del blog fa il parsing dei due file (mi limito a riportare il codice relativo alle note):

    codice:
    <xsl:template match="w:r">
      <xsl:if test="w:footnoteReference">
        <xsl:text>\footnote{ </xsl:text>
        <xsl:call-template name="footnote">
          <xsl:with-param name="fid"> 
            <xsl:value-of select="//@w:id" />
          </xsl:with-param>
         </xsl:call-template>
         <xsl:text>}</xsl:text>
       </xsl:if>
    </xsl:template>
    
    <xsl:template name="footnote">
     <xsl:param name="fid" />
     <xsl:apply templates select="document('footnotes.xml')/w:footnotes/w:footnote[@w:id=$fid]" />
    </xsl:template>
    
    <xsl:template match="//w:footnote">
     <xsl:apply-templates select="w:p" />
    </xsl:template>
    La linea di principio è semplice: il codice cerca il nodo footnoteReference nel primo file, memorizza il valore dell'attributo w:id nel parametro fid e lo passa al template "footnote", il quale fa il parsing di footnotes.xml e cerca la nota con w:id = fid per poi estrarre il testo contenuto in w.

    C'è però qualcosa che fa sì che la procedura di volta in volta riporti fid al valore 1 iniziale.

    Qualcuno di voi saprebbe spiegarmi come mai il codice non funziona correttamente? Sono agli inizi con XSL (ma conosco discretamente altri linguaggi).

    Grazie !

  2. #2
    ciao ! non vedo for-each nei tuoi template .. come cicli tra le note per prendere i diversi fid ?

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2008
    Messaggi
    18
    Non c'è nessun for-each in effetti.

    Però è anche vero che non si tratta di un blocco di istruzioni da ripetere ciclicamente in modo regolare, ma di un blocco da eseguire solo qualora se ne verifichino le condizioni.

    Quindi, nel testo principale (document.xml) se si incontra un tag w:footnoteReference viene richiamato il template footnote. In questo caso non credo che il ciclo for-each sarebbe adeguato.

    Invece nel testo secondario (footnotes.xml) la nota dovrebbe essere recuperata attraverso :

    codice:
    <xsl:apply templates select="document('footnotes.xml')/w:footnotes/w:footnote[@w:id=$fid]" />
    che dovrebbe selezionare direttamente il nodo footnote con attributo w:id=$fid.
    E' possibile che invece qui serva un for-each ?

  4. #4
    codice:
    <xsl:template match="w:p">
    	<xsl:for-each select="w:r">
    		<xsl:if test="w:footnoteReference">
    			<xsl:text>\footnote{ </xsl:text>
    			<xsl:call-template name="footnote">
    				<xsl:with-param name="fid">
    					<xsl:value-of select="//@w:id" />
    				</xsl:with-param>
    			</xsl:call-template>
    			<xsl:text>}</xsl:text>
    		</xsl:if>
    	</xsl:for-each>
    </xsl:template>
    prova con questo

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2008
    Messaggi
    18
    Ciao,

    Grazie per il suggerimento. Ho provato, ma purtroppo continua a darmi sempre e solo il testo della nota numero 1.

    Il codice completo, inclusa la tua modifica e qualche riga aggiuntiva che avevo omesso per semplicità, adesso è questo:

    codice:
    <xsl:template match="w:p">
      <xsl:apply-templates/>
         <xsl:if test="position()!=last()">
             <xsl:text> </xsl:text>
         </xsl:if>
     
      <xsl:for-each select="w:r">
           <xsl:if test="w:footnoteReference"><xsl:text>\footnote{</xsl:text>
                <xsl:call-template name="footnote">
                     <xsl:with-param name="fid"><xsl:value-of select="//@w:id"/></xsl:with-param>
                </xsl:call-template>
                <xsl:text>}</xsl:text>
           </xsl:if>
     
           <xsl:if test="w:rPr/w:b"><xsl:text>\textbf{</xsl:text></xsl:if>
           <xsl:call-template name="pastb"/>
            <xsl:if test="w:rPr/w:b"><xsl:text>}</xsl:text></xsl:if>
      </xsl:for-each>
    </xsl:template>
    Però continua a non funzionare.

  6. #6
    Utente di HTML.it
    Registrato dal
    Mar 2008
    Messaggi
    18
    E se invece di leggere il w:id inserissi il conteggio dei nodi footnoteReference ?
    In fondo le note dovrebbero seguire una numerazione progressiva.
    Devo guardare un po' in rete come si usa la funzione count() in XSLT.

    E mi rimane poco chiaro come mai il codice originale non recuperi le note correttamente...

  7. #7
    codice:
    <xsl:variable name="fileconifootnoteReference" select="document(fileconifootnoteReference.xml)"/>
    <xsl:variable name="fileconiTestodellanota" select="document(fileconiTestodellanota.xml)"/>
    
    
    <xsl:template match="/">
    	<xsl:for-each select="$fileconifootnoteReference/w:document/w:body/w:p/w:r[w:footnoteReference/@w:id != '']">
    		<xsl:variable name="current_note_id" select="w:footnoteReference/@w:id"/>
    		<xsl:for-each select="$fileconiTestodellanota/w:footnotes/*[@w:id = $current_note_id]">
    			<xsl:text>\footnote{ </xsl:text>
    			<xsl:value-of select="w:p/w:r/w:t"/>
    			<xsl:text>}</xsl:text>
    		</xsl:for-each>
    	</xsl:for-each>
    </xsl:template>

  8. #8
    Utente di HTML.it
    Registrato dal
    Mar 2008
    Messaggi
    18
    No, neanche così. Ma grazie per i suggerimenti: a forza di fare delle prove ho trovato l'errore.

    In realtà non serve il ciclo for-each, e nemmeno il test if.

    Bisogna sostituire la seguente porzione di codice:

    codice:
    <xsl:template match="w:r">
      <xsl:if test="w:footnoteReference">
        <xsl:text>\footnote{ </xsl:text>
        <xsl:call-template name="footnote">
          <xsl:with-param name="fid"> 
            <xsl:value-of select="//@w:id" />
          </xsl:with-param>
         </xsl:call-template>
         <xsl:text>}</xsl:text>
       </xsl:if>
    </xsl:template>
    Con questa:

    codice:
    <xsl:template match="w:footnoteReference">
          <xsl:text>\footnote{ </xsl:text>
        <xsl:call-template name="footnote">
          <xsl:with-param name="fid"> 
            <xsl:value-of select="@w:id" />
          </xsl:with-param>
         </xsl:call-template>
         <xsl:text>}</xsl:text>
    </xsl:template>
    Grazie comunque per l'attenzione !

  9. #9
    HAHAHA ti giuro che ci avevo pensato ma ho detto non può essere quello :P

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.