3 votes

Code XSLT nécessaire pour styliser du texte entre 2 éléments

J'espère que quelqu'un pourra me donner un coup de main. Cela fait plusieurs jours que je suis confronté à ce problème. La racine de mon problème est que je veux ajouter du balisage à tous les noeuds dans l'ordre du document entre 2 éléments.

J'ai un document qui contient un XML similaire à celui-ci :

<Employees>
  <Employee>
    <Title>Mr.</Title>
    <FirstName>John</FirstName>
    <LastName>Doe</LastName>
</Employee>
  <Employee>
    <Title>Mr.</Title>
    <FirstName>Tom</FirstName>
    <LastName>Doe</LastName>
  </Employee>
</Employees>

Lorsque j'utilise la fonction "markup" d'Oracle, qui marque les résultats de recherche, et que je recherche la chaîne "John Doe", j'obtiens un résultat XML comme celui-ci :

<Employees>
  <Employee>
    <Title>Mr.</Title>
    <FirstName><hitStart/>John</FirstName>
    <LastName>Doe<hitEnd/></LastName>
  </Employee>
  <Employee>
    <Title>Mr.</Title>
    <FirstName>Tom</FirstName>
    <LastName>Doe</LastName>
  </Employee>
</Employees>

Je veux transformer cela en XHTML qui met en évidence le hit. Par exemple, le XHTML suivant serait un résultat utile :

<TABLE>
  <TR>
    <TD>Mr. <b style="color:red">John Doe</b></TD>
  <TR>
  <TR>
    <TD>Tom Doe</TD>
  </TR>
</TABLE>

J'ai essayé d'écrire des feuilles de style qui utilisent des apply-templates ou des named templates pour naviguer dans le document, mais je n'arrive pas à les faire fonctionner. L'utilisation de apply-templates est délicate car je ne peux pas passer un paramètre qui indique si les nœuds se trouvent ou non dans les éléments hitStart et hitEnd. L'utilisation de named templates est délicate car je dois traiter différemment les nœuds de texte et d'élément, ce que je ne peux pas faire avec XSLT 1.0. Une aide serait appréciée.

Merci, Brian

Merci à tous ceux qui ont aidé !!!! Vous êtes géniaux !

Voici ce que j'ai décidé :

<xsl:template match="/*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="node()[1]"/>
    </xsl:copy>
    <xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="text()[preceding::*[self::hitStart or self::hitEnd][1][self::hitStart]
and following::*[self::hitStart or self::hitEnd][1][self::hitEnd]]">
    <span style="color:red;font-style:italic;font-weight:bold"><xsl:value-of select="."/></span>
    <xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="hitStart|hitEnd">
    <xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>

3voto

Dimitre Novatchev Points 147842

Cette transformation :

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

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

 <xsl:template match=
   "text()
      [preceding::*[self::hitStart or self::hitEnd][1][self::hitStart]
     and
       following::*[self::hitStart or self::hitEnd][1][self::hitEnd]
      ]">
    <xsl:value-of select="concat('*** ', ., ' ***')"/>
  </xsl:template>

 <xsl:template match="hitStart|hitEnd">
    <xsl:apply-templates select="following-sibling::node()[1]"/>
  </xsl:template>
 </xsl:stylesheet>

lorsqu'il est appliqué au document XML fourni :

<Employees>
  <Employee>
    <Title>Mr.</Title>
    <FirstName><hitStart/>John</FirstName>
    <LastName>Doe<hitEnd/></LastName>
  </Employee>
  <Employee>
    <Title>Mr.</Title>
    <FirstName>Tom</FirstName>
    <LastName>Doe</LastName>
  </Employee>
</Employees>

met en évidence chaque nœud de texte situé entre les deux hitStart y hitEnd en l'entourant de trois astérisques et en produisant le résultat voulu et correct. :

<Employees>
   <Employee>
      <Title>Mr.</Title>
      <FirstName>*** John ***</FirstName>
      <LastName>*** Doe ***</LastName>
   </Employee>
   <Employee>
      <Title>Mr.</Title>
      <FirstName>Tom</FirstName>
      <LastName>Doe</LastName>
   </Employee>
</Employees>

Explication :

Utilisation et remplacement de la règle d'identité "à grain fin".

1voto

Patrick Clancey Points 388

Ce n'est pas idéal, mais vous pourriez faire quelque chose de rapide et sale comme...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" encoding="utf-8" indent="no"/>

    <xsl:template match="/">
        <table>
            <xsl:apply-templates />
        </table>
    </xsl:template>

    <xsl:template match="FirstName[hitStart]">
        <span class="alert"><xsl:value-of select="."/>&#160;</span>
    </xsl:template>
    <xsl:template match="FirstName">
        <xsl:value-of select="."/>&#160;
    </xsl:template>
    <xsl:template match="LastName[hitEnd]">
        <span class="alert"><xsl:value-of select="."/></span>
    </xsl:template>
    <xsl:template match="LastName">
        <xsl:value-of select="."/>
    </xsl:template>
    <xsl:template match="Employees/Employee">
        <tr>
            <td>
                <xsl:apply-templates select="Title"/>
            </td>
            <td>
                <xsl:apply-templates select="FirstName | LastName"/>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

0voto

Joepie Points 1483

Solution simple qui utilise la désactivation de l'échappement de sortie pour éviter les erreurs de début d'un élément sans fin, et de fin d'un élément sans élément de début.

<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xhtml" indent="yes"/>

    <xsl:template match="/Employees">
        <TABLE>
            <xsl:apply-templates select="Employee"/>
        </TABLE>
    </xsl:template>

    <xsl:template match="Employee">
        <TR>
            <TD><xsl:apply-templates/></TD>
        </TR>
    </xsl:template>

    <xsl:template match="hitStart">
        <xsl:value-of disable-output-escaping="yes" select="'&lt;b style=&quot;color:red&quot;&gt;'"/>
    </xsl:template>

    <xsl:template match="hitEnd">
        <xsl:value-of disable-output-escaping="yes" select="'&lt;/b&gt;'"/>
    </xsl:template>
</xsl:transform>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X