2009-03-14 15 views
8

Ich schreibe dies, weil ich wirklich die Wand getroffen habe und nicht weitermachen kann. In meiner Datenbank habe ich HTML wie folgt entkommen lassen: "<p>My name is Freddy and I was".XSL Zeichen Flucht Problem

Ich möchte es als HTML anzeigen ODER die HTML-Tags in meiner XSL-Vorlage entfernen. Beide Lösungen werden für mich funktionieren und ich werde die schnellere Lösung wählen.

Ich habe mehrere Beiträge online gelesen, kann aber keine Lösung finden. Ich habe auch disable-output-escape ohne Erfolg versucht. Grundsätzlich scheint es das Problem ist, dass irgendwo in der XSL-Ausführung der Motor diese <p> in diese ändert: <p>.

Es konvertiert die & in &. Wenn es hilft, hier ist mein XSL-Code. Ich habe mehrere Kombinationen mit und ohne das Ausgabe-Tag auf der Oberseite versucht.

Jede Hilfe wird geschätzt. Danke im Voraus.

<?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, ich brauche etwas Hilfe Verständnis, was Sie zu tun versuchen. Ihr XSLT zeigt an, dass versucht wird, HTML auszugeben, aber Sie haben dann eine Vorlage, die angibt, dass Sie HTML-Tags entfernen. Ich bin mir nicht sicher, warum Sie das versuchen. Bitte geben Sie weitere Informationen, wenn Sie können. – Nick

+0

Um etwas über das Problem sagen zu können, wäre es wirklich nützlich, ein Beispiel für eine XML-Eingabe durch das Stylesheet zu haben, das das Problem aufweist und auch zu wissen, welcher XSLT-Prozessor Sie verwenden ... – Laurent

Antwort

6

Sie sollten kein maskiertes HTML in Ihrer Datenbank speichern. Wenn Ihre Datenbank das tatsächliche Zeichen "<" enthält, würde der Befehl "disable-output-escaping" tun, was Sie wollten.

Wenn Sie die Daten nicht ändern können, müssen Sie die Daten vor der Transformation auflösen.

+0

Thks! Ich hatte gerade diesen Einblick: Anstatt zu versuchen, mit der HTML-STRIP-Vorlage unleserlich zu werden, habe ich tatsächlich den STRIP damit gemacht: & lt; und es hat funktioniert. Leider ziehe ich Informationen aus der Tabelle einer anderen Anwendung, und ich kann nicht ändern, wie es funktioniert. Ich benutze DotNetNuke. –

+0

+1. Ich hasse es, wenn Leute solche Strukturen in Datenbanken speichern. Es ist ein Management-Albtraum. –

18

in der Annahme, dass Sie diese HTML-String haben,

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

dann, wenn Sie es ihm entkommen und in einer Datenbank speichern würde es diese werden:

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

Folglich Wenn Sie es als XML abrufen (ohne es vorher zu entsernen), wäre das Ergebnis :

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

und <xsl:value-of select="." disable-output-escaping="yes" /> produzieren würde:

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

Sie erhalten genau die gleiche Sache, die Sie in Ihrer Datenbank haben, aber natürlich können Sie die HTML-Tags in der Ausgabe zu sehen.Also, was Sie brauchen, ist ein Mechanismus, der den folgenden String-Ersatz tut:

  • "&amp;lt;" mit "&lt;" (effektiv &lt;-< in unescaped ouput Wechsel)
  • "&amp;gt;" mit "&gt;" (effektiv &gt;-> in unescaped ouput Wechsel)
  • "&amp;quot;" mit "&quot;" (effektiv &quot; zu " in unescaped ouput Wechsel)
  • "&amp;amp;" mit "&amp;"

Von Ihrem XSL (effektiv &amp;-& in unescaped ouput zu ändern) Ich habe folgende Testeingang XML abgeleitet haben:

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

Ich habe das Stylesheet geändert Sie geliefert und implementiert eine solche Ersatzmechanismus. Wenn Sie die folgende XSLT 1.0 Vorlage angewendet werden:

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

Dann ist dieser Ausgang HTML erzeugt wird:

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

Hinweis

  • die Verwendung eines temporären Namensraum und eingebettete Elemente (<my:unescape>) eine Liste von Zeichen zu erstellen
  • die Verwendung von Rekursion zu ersetzen, einen iterativen Austausch aller betroffenen chara zu emulieren cters in Eingabe
  • die Verwendung des impliziten Kontextes innerhalb der unescape Vorlage, die Informationen zu transportieren, die Zeichen zur Zeit ersetzt werden

Weiterhin beachten:

  • die Verwendung von Templat-Modi verschiedene Ausgangs für den gleichen Eingang (dies ersetzt Ihre templatenumber Parameter)
  • die meiste Zeit zu bekommen gibt es keine Notwendigkeit für <xsl:attribute> Elemente ist. Sie können sicher durch Inline-Notation ersetzt werden (attributename="{attributevalue}")
  • die Verwendung der concat() Funktion erstellen Sie die URL

Im Allgemeinen ist es eine schlechte Idee zu speichern entkam HTML in einer Datenbank (allgemeiner gesprochen: Es ist eine schlechte Idee, HTML in einer Datenbank zu speichern. Sie setzen sich bis zu alle Arten von Problemen zu bekommen, dies ist einer von ihnen. Wenn Sie diese Einstellung nicht ändern können, hoffe ich, dass Ihnen die Lösung hilft.

Ich kann nicht garantieren, dass es das Richtige in allen Situationen der Fall ist, und es kann Sicherheitslücken öffnen (man denke XSS), aber mit dieser Behandlung war nicht Teil der Frage. In jedem Fall sollten Sie sich gewarnt fühlen.

ich brauche eine Pause.;-)

+0

Große Erklärung! –

+0

Danke, ich hatte genau das gleiche Problem :) +1 für deine tolle Antwort. – EinLama

1

Es ist eine schlechte Idee, HTML zu speichern in einer Datenbank

Was? Wie soll man es dann speichern? In einem XML-Dokument müssen Sie also XSLT verwenden? Als Webentwickler haben wir immer SQL-Datenbanken verwendet, um benutzerdefinierte HTML-Daten zu speichern. Es ist nichts falsch an dieser Methode, solange es für Ihre Zwecke richtig keimfrei ist.

+0

Es ist keine gute Übung. Wenn Sie damit durchkommen, arbeiten Sie einfach nicht an einem System, das skalieren musste. – itsbruce

+0

Schlechte Idee oder nein, fast das gesamte Web wird heutzutage von Datenbank-gespeichertem HTML getrieben. WordPress ist ein offensichtliches Beispiel. –

+0

Es könnte weniger mühsam sein, MarkDown anstelle von HTML-Markup zu verwenden. In beiden Fällen ** gibt es ** Anwendungsfälle, in denen eine Art Markup in der Datenbank gespeichert werden soll. – CoDEmanX

2

diese Zeile in Ihrem Stylesheet hinzufügen

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