2017-08-04 1 views
0

En utilisant XSLT sur un fichier XML, mon but est de copier tout le XML en ajoutant un extrait de texte ("(PDF)" dans cet exemple) au dernier bit de texte présent dans un tag particulier sans tenir compte de l'imbrication Le prochain est. J'ai réussi à prendre soin de la plupart des cas de bord et à l'approcher, mais il y a toujours une instance qui me pose problème. Je suis sûr qu'il y a aussi un moyen de le faire plus efficacement afin que tous les conseils sont appréciés.XPath: ajout de texte uniquement à la dernière occurrence text() (quelle que soit la profondeur imbriquée) lors de la copie de tout le code XML.

XML

<links> 
    <a href="something.pdf">This is a PDF file</a> 
    <a href="something.PDF"> 
     <span> 
      <b>This</b> is a PDF file 
     </span> 
    </a> 
    <a href="something.pdF"> 
     <div> 
      <span> 
       This is a PDF file 
      </span> 
     </div> 
    </a> 
    <a href="something.pdf"> 
     <div class="something"> 
      <span> 
       This is a <i>PDF</i> file 
      </span> 
     </div> 
    </a> 
    <a href="something.pDf"> 
     <div class="something"> 
      <div> 
       <div> 
        Test Text 
        <div> 
         This is a <i>PDF</i> 
        </div> 
       </div> 
      </div> 
     </div> 
    </a> 
</links> 

XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output indent="yes" method="xml"/> 
    <xsl:strip-space elements="*" /> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:param name="pdf-append" select="'(PDF)'"/> 

    <xsl:template match="a['.pdf' = substring(translate(@href,'PDF','pdf'), string-length(@href) - 3)]/text()"> 
     <xsl:value-of select="concat(current(),' ', $pdf-append)"/> 
    </xsl:template> 

    <xsl:template match="a['.pdf' = substring(translate(@href,'PDF','pdf'), string-length(@href) - 3)]//node()[last()]/text()[last()]"> 
     <xsl:value-of select="concat(current(),' ', $pdf-append)"/> 
    </xsl:template> 
</xsl:stylesheet> 

Résultat courant

<links> 
<a href="something.pdf">This is a PDF file (PDF)</a> 
    <a href="something.PDF"> 
     <span> 
     <b>This</b> is a PDF file 
     (PDF)</span> 
    </a> 
    <a href="something.pdF"> 
     <div> 
     <span> 
       This is a PDF file 
      (PDF)</span> 
     </div> 
    </a> 
    <a href="something.pdf"> 
     <div class="something"> 
     <span> 
       This is a <i>PDF</i> file 
      (PDF)</span> 
     </div> 
    </a> 
    <a href="something.pDf"> 
     <div class="something"> 
     <div> 
      <div> 
        Test Text 
        (PDF)<div> 
         This is a (PDF)<i>PDF (PDF)</i> 
       </div> 
      </div> 
     </div> 
     </div> 
    </a> 
</links> 

Le dernier <a> est le problème: idéalement "(PDF)" n'apparaîtrait que dans la dernière étiquette <i> (par ex. This is a <i>PDF (PDF)</i>). Donc les questions sont: comment puis-je réparer cette dernière instance?

Merci.

Répondre

0

Que diriez-vous:

XSLT 1,0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:param name="pdf-append" select="' (PDF)'"/> 

<!-- identity transform --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="text()"> 
    <xsl:value-of select="."/> 

    <xsl:variable name="a" select="ancestor::a" /> 
    <xsl:variable name="href" select="$a/@href" /> 
    <xsl:variable name="extension" select="substring(translate($href,'PDF','pdf'), string-length($href) - 3)" /> 
    <xsl:variable name="last-text" select="$a/descendant::text()[last()]" /> 

    <xsl:if test="$extension='.pdf' and generate-id()=generate-id($last-text) "> 
     <xsl:value-of select="$pdf-append"/> 
    </xsl:if> 
</xsl:template> 

</xsl:stylesheet>