2016-04-25 8 views
0

Ich habe eine XML, so etwas wie dieses:XSLT regulären Ausdruck Sequenzen entfernen Text

<?xml version="1.0" encoding="UTF-8"?> 
     <earth> 
    <computer> 
      <parts>;;remove;;This should stay;;remove too;;This stay;;yeah also remove;;this stay </parts> 

     </computer> 
    </earth> 

Ich möchte eine XSLT erstellen 2.0 verwandeln den gesamten Text zu entfernen, die beginnt und endet mit ;;

<?xml version="1.0" encoding="utf-8"?> 
<earth> 
    <computer> 
      <parts>This should stay This stay this stay </parts> 
     </computer> 

    </earth> 

Versuchen Sie, so etwas zu tun, aber kein Glück:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" 
    exclude-result-prefixes="fn"> 
    <xsl:output encoding="utf-8" method="xml" indent="yes" /> 
    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="parts"> 
    <xsl:element name="parts" > 
       <xsl:value-of select="replace(., ';;.*;;','')" /> 
      </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 
+1

. * ist ein gieriger Treffer; es wird alle ";;" schlucken Begrenzer bis zum letzten. Sie könnten es durch eine nicht gierige Übereinstimmung ersetzen (. *?) Oder vermeiden Sie passende Semikola wie in der Lösung von @ michael.hor257k –

Antwort

0

Ein anderer Ansatz werden tokenize würde auf ";;" Als Trennzeichen entfernen Sie dann alle geradzahligen Tokens:

<xsl:template match="parts"> 
    <parts> 
    <xsl:value-of select="tokenize(.,';;')[position() mod 2 = 1]" 
    separator=""/> 
    </parts> 
</xsl:template> 
+0

Dies setzt voraus, dass das erste Token immer entfernt werden muss - und mit einer Eingabe wie " behalten ;; entfernen ;; behalten". –

+0

Ich glaube nicht; sicherlich sowohl in diesem Fall als auch in dem gelieferten Fall ist das erste "Entfernen" Token 2? –

+0

Ich habe dies erneut überprüft. Das Problem ist, dass Sie die Parität umgekehrt haben: es sollte '[position() mod 2 = 1]' sein. –

0

XSLT 1.0

Für diese Art von Sache würde ich Rekursion verwenden. Mit string replace können Sie vor und nach einem bestimmten Zeichen (oder einer Menge von Zeichen) erhalten. Alles, was Sie ist ständig Schleife über die Zeichenfolge tun müssen, bis es keine weiteren Vorkommen des Zeichens ersetzen sind, wie folgt:

<xsl:template name="string-remove-between"> 
    <xsl:param name="text" /> 
    <xsl:param name="remove" /> 

    <xsl:choose> 
     <xsl:when test="contains($text, $remove)"> 
      <xsl:value-of select="substring-before($text,$remove)" /> 
      <xsl:call-template name="string-remove-between"> 
       <xsl:with-param name="text" select="substring-after(substring-after($text,$remove), $remove)" /> 
       <xsl:with-param name="remove" select="$remove" /> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$text"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

Dann würden Sie nur die Vorlage mit Text abrufen und den Abschnitt, den Sie entfernen möchten :

<xsl:call-template name="string-remove-between"> 
    <xsl:with-param name="text" select="parts"/> 
    <xsl:with-param name="remove">;;</xsl:with-param> 
</xsl:call-template> 

Beachten Sie, dass zwei substring-after Anrufe gibt es, dies stellt sicher, wir die zweite Instanz der ersetzen Zeichen bekommen ‚;;‘ also ziehen wir den Text nicht dazwischen.

+0

Thx, nette Lösung. Ich erkannte, dass das erwartete Ergebnis bekomme ich diese einfache Änderung meines Codes (verwenden Sie widerwillige Quantifikatoren?): Select = "ersetzen (., ';;. +? ;;",' ') " – Wait

+0

Ja, ich wusste nicht in Ihre Frage, die Sie erwähnten, war XSLT 2.0, mit dem ich nicht so vertraut bin. Ich werde meine Lösung aktualisieren, falls jemand anderes darauf stößt und 1.0 verwendet. –

1

Wow, was für eine dumme Art, Text zu markieren. Sie haben XML zur Verfügung, warum nicht verwenden? Und selbst wenn Sie diesen Weg markieren, warum verwenden Sie nicht unterschiedliche Symbole zum Öffnen und Schließen der markierten Teile?

Wie auch immer, ich glaube, das ist das erwartete Ergebnis zurückgibt:

XSLT 2,0

<xsl:stylesheet version="2.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="*"/> 

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

<xsl:template match="parts"> 
    <xsl:copy> 
     <xsl:value-of select="replace(., ';;.+?;;', '')" /> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet>