2008-08-27 19 views
4

ich find bin Durchführung und ersetzen auf dem Zeilenvorschub-Zeichen (
) und mit dem Absatz schließen und Absatz öffnet Tags ersetzt den folgenden Code verwenden:Suchen und Ersetzen mit einzigartigen

<xsl:template match="/STORIES/STORY"> 
    <component> 
     <xsl:if test="boolean(ARTICLEBODY)"> 
      <p> 
       <xsl:call-template name="replace-text"> 
         <xsl:with-param name="text" select="ARTICLEBODY" /> 
         <xsl:with-param name="replace" select="'&#10;'" /> 
         <xsl:with-param name="by" select="'&lt;/p&gt;&lt;p&gt;'" /> 
       </xsl:call-template> 
      </p> 
     </xsl:if> 
    </component> 
</xsl:template> 

<xsl:template name="replace-text"> 
    <xsl:param name="text"/> 
    <xsl:param name="replace" /> 
    <xsl:param name="by" /> 

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

Diese fast perfekt funktioniert , außer dass ich es wirklich brauche, um die Zeilenvorschübe zu duplexieren, da die Absätze dazu neigen, durch 2 oder mehr getrennt zu werden, was zu </p><p></p><p> führt.

Ist es möglich, es so zu bekommen, dass es nur dieses einmal pro Absatz jemals ersetzen wird?

Antwort

5

disable-output-escaping ist nicht böse in sich selbst, aber es gibt nur wenige Fälle, in denen Sie es verwenden sollten, und das ist keiner von ihnen. In XSLT arbeiten Sie mit Bäumen, nicht Markup-String. Hier ist eine XSTL 1.0 Lösung:

<xsl:template match="/STORIES/STORY"> 
    <component> 
    <xsl:if test="ARTICLEBODY"> 
     <xsl:call-template name="wrap-text"> 
     <xsl:with-param name="text" select="ARTICLEBODY"/> 
     <xsl:with-param name="delimiter" select="'&#10;'"/> 
     <xsl:with-param name="element" select="'p'"/> 
     </xsl:call-template> 
    </xsl:if> 
    </component> 
</xsl:template> 

<xsl:template name="wrap-text"> 
    <xsl:param name="text"/> 
    <xsl:param name="delimiter"/> 
    <xsl:param name="element"/> 

    <xsl:choose> 
    <xsl:when test="contains($text, $delimiter)"> 
     <xsl:variable name="t" select="substring-before($text, $delimiter)"/> 
     <xsl:if test="normalize-space($t)"> 
     <xsl:element name="{$element}"> 
     <xsl:value-of select="$t"/> 
     </xsl:element> 
     </xsl:if>   
     <xsl:call-template name="wrap-text"> 
     <xsl:with-param name="text" select="substring-after($text, $delimiter)"/> 
     <xsl:with-param name="delimiter" select="$delimiter"/> 
     <xsl:with-param name="element" select="$element"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:if test="normalize-space($text)"> 
     <xsl:element name="{$element}"> 
      <xsl:value-of select="$text"/> 
     </xsl:element> 
     </xsl:if> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
1

Angesichts der XPath-Funktionen, die Sie anrufen, die ich nicht erinnere, den Luxus in meiner MSXSL-Arbeit zu haben, sieht es so aus, als ob Sie einen XPath 2-kompatiblen Prozessor verwenden.

Wenn dies der Fall ist, hat XPath 2 keine Funktion zum Ersetzen (Zeichenfolge, Muster, Ersetzung), die eine Regex als zweiten Parameter verwendet?

Es könnte helfen, einige Beispiel-Xml-Eingabe zu haben und zu wissen, welchen Prozessor Sie verwenden möchten.

Aus Ihrem ursprünglichen Beispiel scheint es, dass die doppelten Absätze alle ein Nur-Leerzeichen-Präfix haben. So etwas wie diese leichte Modifikation könnte die Betrogenen trimmen.

<xsl:when test="contains($text, $replace)"> 
    <xsl:variable name="prefix" select="substring-before($text, $replace)" /> 
    <xsl:choose> 
    <xsl:when test="normalize-string($prefix)!=''"> 
     <xsl:value-of select="$prefix"/> 
     <xsl:value-of select="$by" disable-output-escaping="yes"/> 
    </xsl:when> 
    </xsl:choose> 
    <xsl:call-template name="replace-text"> 
    <xsl:with-param name="text" select="substring-after($text, $replace)"/> 
    <xsl:with-param name="replace" select="$replace" /> 
    <xsl:with-param name="by" select="$by" /> 
    </xsl:call-template> 

1

starten (XSLT 2.0):

<xsl:template match="/STORIES/STORY"> 
     <component> 
      <xsl:if test="boolean(ARTICLEBODY)"> 
       <xsl:call-template name="insert_paras"> 
        <xsl:with-param name="text" select="ARTICLEBODY/text()"/> 
       </xsl:call-template> 
      </xsl:if> 
     </component> 
    </xsl:template> 

    <xsl:template name="insert_paras"> 
     <xsl:param name="text" /> 

     <xsl:variable name="regex"> 
      <xsl:text>&#10;(&#10;|\s)*</xsl:text> 
     </xsl:variable> 
     <xsl:variable name="tokenized-text" select="tokenize($text, $regex)"/> 

     <xsl:for-each select="$tokenized-text"> 
      <p> 
       <xsl:value-of select="."/> 
      </p> 
     </xsl:for-each> 
    </xsl:template> 

Es ist generell eine schlechte Idee Literalzeichenfolgen zu verwenden, in XML-Markup zu setzen, da Sie nicht garantieren können, dass die Ergebnisse ausgewogen.