2009-03-14 8 views
8

J'écris ceci parce que j'ai vraiment frappé le mur et je ne peux pas aller de l'avant. Dans ma base de données j'ai échappé au HTML comme ceci: "<p>My name is Freddy and I was". Je veux l'afficher en HTML OU supprimer les balises HTML dans mon modèle XSL. Les deux solutions fonctionneront pour moi et je choisirai la solution la plus rapide.Problème d'échappement de caractères XSL

J'ai lu plusieurs articles en ligne mais je ne trouve pas de solution. J'ai aussi essayé disable-output-escape sans succès. Fondamentalement, il semble que le problème est que quelque part dans l'exécution de XSL le moteur change ceci <p> en ceci: <p>. Il convertit & en &. Si ça aide, voici mon code XSL. J'ai essayé plusieurs combinaisons avec et sans l'étiquette de sortie sur le dessus.

Toute aide sera appréciée. Merci d'avance.

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="html" omit-xml-declaration="yes"/> 

    <xsl:template match="DocumentElement"> 
    <div> 
     <xsl:attribute name="id">mySlides</xsl:attribute> 
     <xsl:apply-templates> 
     <xsl:with-param name="templatenumber" select="0"/> 
     </xsl:apply-templates> 
    </div> 

    <div> 
     <xsl:attribute name="id">myController</xsl:attribute> 
     <xsl:apply-templates> 
     <xsl:with-param name="templatenumber" select="1"/> 
     </xsl:apply-templates> 
    </div> 
    </xsl:template> 

    <xsl:template match="DocumentElement/QueryResults"> 
    <xsl:param name="templatenumber">tobereplace</xsl:param> 

    <xsl:if test="$templatenumber=0"> 
     <div> 
     <xsl:attribute name="id">myController</xsl:attribute> 
     <div> 
      <xsl:attribute name="class">article</xsl:attribute> 
      <h2> 
      <a> 
       <xsl:attribute name="class">title</xsl:attribute> 
       <xsl:attribute name="title"><xsl:value-of select="Title"/></xsl:attribute> 
       <xsl:attribute name="href">/stories/stories-details/articletype/articleview/articleid/<xsl:value-of select="ArticleId"/>/<xsl:value-of select="SEOTitle"/>.aspx</xsl:attribute> 
       <xsl:value-of select="Title"/> 
      </a> 
      </h2> 
      <div> 
      <xsl:attribute name="style">text-indent: 25px;</xsl:attribute> 
      <xsl:attribute name="class">articlesummary</xsl:attribute> 
      <xsl:call-template name="removeHtmlTags"> 
       <xsl:with-param name="html" select="Summary" /> 
      </xsl:call-template> 
      </div> 
     </div> 
     </div> 
    </xsl:if> 
    <xsl:if test="$templatenumber=1"> 
     <div> 
     <xsl:attribute name="id">myController</xsl:attribute> 
     <span> 
      <xsl:attribute name="class">jFlowControl</xsl:attribute> 
      aa 
     </span> 
     </div> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template name="removeHtmlTags"> 
    <xsl:param name="html"/> 
    <xsl:choose> 
     <xsl:when test="contains($html, '&lt;')"> 
     <xsl:value-of select="substring-before($html, '&lt;')"/> 
     <!-- Recurse through HTML --> 
     <xsl:call-template name="removeHtmlTags"> 
      <xsl:with-param name="html" select="substring-after($html, '&gt;')"/> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="$html"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 
+0

@Marcos, j'ai besoin d'aide pour comprendre ce que vous essayez de faire. Votre code XSLT indique qu'il tente de générer du code HTML, mais vous disposez alors d'un modèle indiquant que vous supprimez des balises HTML. Je ne sais pas pourquoi vous essayez de faire cela. S'il vous plaît donner plus d'informations si vous le pouvez. – Nick

+0

Pour être en mesure de dire quelque chose sur le problème, il serait vraiment utile d'avoir un exemple d'entrée XML à exécuter dans la feuille de style et qui présente le problème, et aussi de savoir quel processeur XSLT vous utilisez ... – Laurent

Répondre

6

Vous ne devez pas stocker de code HTML échappé dans votre base de données. Si votre base de données contenait le caractère "<", la commande "disable-output-escaping" ferait ce que vous vouliez.

Si vous ne pouvez pas modifier les données, vous devrez désactiver les données avant d'effectuer la transformation.

+0

Thks! J'ai eu cette perspicacité en ce moment: Au lieu d'essayer d'unescape

+0

+1. Je déteste quand les gens stockent des structures comme celle-ci dans les bases de données. C'est un cauchemar de gestion. –

18

Basé dans l'hypothèse que vous avez cette chaîne HTML,

<p>My name is Freddy &amp; I was 

alors si vous échapper et de le stocker dans une base de données deviendrait cette:

&lt;p&gt;My name is Freddy &amp;amp; I was 

Par conséquent , si vous le récupérez en XML (sans le décocher au préalable), le résultat sera ce:

&amp;lt;p&amp;gt;My name is Freddy &amp;amp;amp; I was 

et <xsl:value-of select="." disable-output-escaping="yes" /> produirait:

&lt;p&gt;My name is Freddy &amp;amp; I was 

Vous obtenez exactement la même chose que vous avez dans votre base de données, mais bien sûr vous voir les balises HTML dans la sortie.Donc ce que vous avez besoin est un mécanisme qui effectue les opérations de remplacement de chaîne suivantes:

  • "&amp;lt;" avec "&lt;" (changer efficacement &lt;-< en ouput non échappés)
  • "&amp;gt;" avec "&gt;" (changer efficacement &gt;-> en séquence d'échappement ouput)
  • "&amp;quot;"
  • avec "&quot;" (en changeant de manière efficace &quot; à " dans unescaped ouput)
  • "&amp;amp;" avec "&amp;" (changer efficacement &amp;-& en ouput non échappés)

De votre XSL je déduire le XML d'entrée de test suivant:

<DocumentElement> 
    <QueryResults> 
    <Title>Article 1</Title> 
    <ArticleId>1</ArticleId> 
    <SEOTitle>Article_1</SEOTitle> 
    <Summary>&amp;lt;p&amp;gt;Article 1 summary &amp;amp;amp; description.&amp;lt;/p&amp;gt;</Summary> 
    </QueryResults> 
    <QueryResults> 
    <Title>Article 2</Title> 
    <ArticleId>2</ArticleId> 
    <SEOTitle>Article_2</SEOTitle> 
    <Summary>&amp;lt;p&amp;gt;Article 2 summary &amp;amp;amp; description.&amp;lt;/p&amp;gt;</Summary> 
    </QueryResults> 
</DocumentElement> 

J'ai changé la feuille de style que vous avez fourni et mis en œuvre un tel mécanisme de remplacement. Si vous appliquez le modèle XSLT 1.0 ci-dessous pour elle:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="my:namespace" 
    exclude-result-prefixes="my" 
> 

    <xsl:output method="html" omit-xml-declaration="yes"/> 

    <my:unescape> 
    <my:char literal="&lt;" escaped="&amp;lt;" /> 
    <my:char literal="&gt;" escaped="&amp;gt;" /> 
    <my:char literal="&quot;" escaped="&amp;quot;" /> 
    <my:char literal="&amp;" escaped="&amp;amp;" /> 
    </my:unescape> 

    <xsl:template match="DocumentElement"> 
    <div id="mySlides"> 
     <xsl:apply-templates mode="slides" /> 
    </div> 
    <div id="myController"> 
     <xsl:apply-templates mode="controller" /> 
    </div> 
    </xsl:template> 

    <xsl:template match="DocumentElement/QueryResults" mode="slides"> 
    <div class="article"> 
     <h2> 
     <a class="title" title="{Title}" href="{concat('/stories/stories-details/articletype/articleview/articleid/', ArticleId, '/', SEOTitle, '.aspx')}"> 
      <xsl:value-of select="Title"/> 
     </a> 
     </h2> 
     <div class="articlesummary" style="text-indent: 25px;"> 
     <xsl:apply-templates select="document('')/*/my:unescape/my:char[1]"> 
      <xsl:with-param name="html" select="Summary" /> 
     </xsl:apply-templates> 
     </div> 
    </div> 
    </xsl:template> 

    <xsl:template match="DocumentElement/QueryResults" mode="controller"> 
    <span class="jFlowControl"> 
     <xsl:text>aa </xsl:text> 
     <xsl:value-of select="Title" /> 
    </span> 
    </xsl:template> 

    <xsl:template match="my:char"> 
    <xsl:param name="html" /> 
    <xsl:variable name="intermediate"> 
     <xsl:choose> 
     <xsl:when test="following-sibling::my:char"> 
      <xsl:apply-templates select="following-sibling::my:char[1]"> 
      <xsl:with-param name="html" select="$html" /> 
      </xsl:apply-templates> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$html" disable-output-escaping="yes" /> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 
    <xsl:call-template name="unescape"> 
     <xsl:with-param name="html" select="$intermediate" /> 
    </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="unescape"> 
    <xsl:param name="html" /> 
    <xsl:choose> 
     <xsl:when test="contains($html, @escaped)"> 
     <xsl:value-of select="substring-before($html, @escaped)" disable-output-escaping="yes"/> 
     <xsl:value-of select="@literal" disable-output-escaping="yes" /> 
     <xsl:call-template name="unescape"> 
      <xsl:with-param name="html" select="substring-after($html, @escaped)"/> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="$html" disable-output-escaping="yes"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

Ensuite, cette sortie HTML est produit:

<div id="mySlides"> 
    <div class="article"> 
    <h2> 
     <a class="title" title="Article 1" href="/stories/stories-details/articletype/articleview/articleid/1/Article_1.aspx">Article 1</a> 
    </h2> 
    <div class="articlesummary" style="text-indent: 25px;"> 
     <p>Article 1 summary &amp; description.</p> 
    </div> 
    </div> 
    <div class="article"> 
    <h2> 
     <a class="title" title="Article 2" href="/stories/stories-details/articletype/articleview/articleid/2/Article_2.aspx">Article 2</a> 
    </h2> 
    <div class="articlesummary" style="text-indent: 25px;"> 
     <p>Article 2 summary &amp; description.</p> 
    </div> 
    </div> 
</div> 
<div id="myController"> 
    <span class="jFlowControl">aa Article 1</span> 
    <span class="jFlowControl">aa Article 2</span> 
</div> 

Remarque

  • l'utilisation d'un espace de noms temporaire et éléments intégrés (<my:unescape>) pour créer une liste de caractères à remplacer
  • l'utilisation de la récursivité pour émuler un remplacement itératif de toutes les chara affectées cters dans l'entrée
  • l'utilisation du contexte implicite dans le modèle unescape pour transporter les informations dont le caractère doit être remplacé au moment

noter En outre:

  • l'utilisation des modes de modèle pour obtenir une sortie différente pour la même entrée (ceci remplace votre templatenumber paramètre)
  • la plupart du temps il n'y a pas besoin d'éléments <xsl:attribute>. Ils peuvent sans risque être remplacée par la notation en ligne (attributename="{attributevalue}")
  • l'utilisation de la fonction concat() pour créer l'URL

D'une manière générale, il est une mauvaise idée de stocker échappé HTML dans une base de données (plus généralement: C'est une mauvaise idée de stocker du HTML dans une base de données.). Vous vous êtes mis en tête d'avoir toutes sortes de problèmes, ceci étant l'un d'entre eux. Si vous ne pouvez pas changer cette configuration, j'espère que la solution vous aidera.

Je ne peux pas garantir qu'il fait la bonne chose dans toutes les situations, et il peut ouvrir des failles de sécurité (pensez XSS), mais cela ne faisait pas partie de la question. Dans tous les cas, considérez-vous averti.

J'ai besoin d'une pause maintenant.;-)

+0

Bonne explication! –

+0

Merci, j'ai eu exactement le même problème :) +1 pour votre excellente réponse. – EinLama

1

Il est une mauvaise idée de stocker HTML dans une base de données

Quoi? Comment allez-vous le stocker alors? Dans un document XML, vous devez donc utiliser XSLT? En tant que développeur Web, nous avons toujours utilisé des bases de données SQL pour stocker des données HTML définies par l'utilisateur. Il n'y a rien de mal avec cette méthode tant qu'elle est correctement désinfectée pour vos besoins.

+0

Ce n'est pas une bonne pratique. Si vous vous en tiriez, vous ne travailliez pas sur un système qui devait évoluer. – itsbruce

+0

Mauvaise idée ou non, presque tout le web est piloté par HTML stocké par la base de données ces jours-ci. WordPress est un exemple évident. –

+0

Il pourrait être moins gênant d'utiliser MarkDown au lieu du balisage HTML. D'une manière ou d'une autre, il y a ** des cas d'utilisation dans lesquels vous voulez stocker un type de balisage dans la base de données. – CoDEmanX

2

Ajouter cette ligne à votre feuille de style

<xsl:output method="html" indent="yes" version="4.0"/>