Janine: Filtern von Trennstrichen (regular expressions)

Hallo miteinander,

seit gestern quäle ich mich mit dem Filter für Trennstriche und hoffe, hier auf gute Anregungen oder Tipps zu kommen.

Ich will folgende vier Problemfälle filtern:

  • Klein- buch- stab- en -> Kleinbuchstaben (Minus & Leerzeichen weg)
  • Groß- Buch- Stab- En -> Groß-Buch-Stab-En (Leerzeichen weg)
  • Reinigungs- oder Hygienevorschrift -> Reinigungs- oder Hygienevorschrift (so belassen)
  • Gedanken - Strich -> Gedanken - Strich (so belassen)

Dazu habe ich die einfache Testdatei:

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<text>
		Klein- buch- stab- en
		Funkt- ionale System- risiko- analyse
		Projekt- organisa- tions- plan
		
		Groß- Buch- Stab- En
		Maschinen- Risiko- analyse
		Ferti- gungs- Prüf- vor- schrift
		
		und oder
		Prozess- und Komponenten- manage- ment- plan
		Reinigungs- oder Hygiene- vorschrift
		
		Gedanken - Strich
		Prozess- über- sicht - Stufe 2
		Entwickler - Software
	</text>
</root>

Für den Fall 1-3 funktioniert das folgende Skript ganz prima:

<xsl:template match="//text">
		<root>
			<xsl:variable name="fstChange">
				<xsl:analyze-string select="." regex="-(&#xa;|\s|\n)([A-Z])">
					<xsl:matching-substring>-<xsl:value-of select="regex-group(2)"/></xsl:matching-substring>
					<xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
				</xsl:analyze-string>
			</xsl:variable>
			<xsl:variable name="finalChange">
				<xsl:analyze-string select="$fstChange" regex="-(&#xa;|\s|\n| )(and|und|oder|or )?">
					<xsl:matching-substring>
						<xsl:choose>
							<xsl:when test="regex-group(2) = 'und'">- und</xsl:when>
							<xsl:when test="regex-group(2) = 'oder'">- oder</xsl:when>
							<xsl:when test="regex-group(2) = 'and'">- and</xsl:when>
							<xsl:when test="regex-group(2) = 'or'">- or</xsl:when>
							<xsl:otherwise></xsl:otherwise>
						</xsl:choose>
					</xsl:matching-substring>
					<xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
				</xsl:analyze-string>
			</xsl:variable>
			<xsl:value-of select="$finalChange"/>
		</root>
	</xsl:template>

Und für die Gedankenstriche klappt das hier:

<xsl:template match="//text">
		<root>
			<xsl:variable name="finalChange">
				<xsl:analyze-string select="." regex="(&#xa;|\s|\n)-(&#xa;|\s|\n)">
					<xsl:matching-substring><xsl:value-of select="regex-group(1)"/>-<xsl:value-of select="regex-group(2)"/></xsl:matching-substring>
					<xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
				</xsl:analyze-string>
			</xsl:variable>
			<xsl:value-of select="$finalChange"/>
		</root>
	</xsl:template>

Mein Problem ist nun, beides zusammenzupacken. Wenn ich alles in ein Template schreibe (mit der Variablen "secChange"), wird meine Gedankenstrich-Variable dennoch übergangen. Habt ihr eine Ahnung, warum? Oder gibt es eine elegantere Möglichkeit?

Bin für jeden Hinweis dankbar! Liebe Grüße, Janine

akzeptierte Antworten

  1. @@Janine

    • Gedanken - Strich -> Gedanken - Strich (so belassen)

    So belassen? Merke: Der Bindestrich steht nie zwischen zwei Leerzeichen!Binde- und Gedankenstrich

    LLAP 🖖

    --
    Ist diese Antwort anstößig? Dann könnte sie nützlich sein.
    1. Es geht hierbei um den Gedankenstrich, nicht um den Bindestrich ;)

      Wie im Beispiel: "Prozessübersicht - Stufe 2" oder wie in der Formatierungsvorlage meines Unternehmens: "Entwickler - Software"

      1. @@Janine

        Es geht hierbei um den Gedankenstrich, nicht um den Bindestrich ;)

        Wie im Beispiel: "Prozessübersicht - Stufe 2" oder wie in der Formatierungsvorlage meines Unternehmens: "Entwickler - Software"

        Eben. Der Bindestrich '-' ist kein Gedankenstrich; der Halbgeviertstrich '–' ist einer.

        Wie in „Prozessübersicht – Stufe 2“ oder „Entwickler – Software“.

        LLAP 🖖

        obiger Text in Proportionalschrift

        --
        Ist diese Antwort anstößig? Dann könnte sie nützlich sein.
        1. Es ist mir egal, wie der Strich heißt oder wie lang er ist. Es geht mir bei dem Problem lediglich um den XSL-Code und dass ich in den angegebenen Beispielen zum einen Strich und Leerzeichen filtern und zum anderen Leerzeichen, Strich und Leerzeichen beibehalten will.

          Eine typografische Diskussion sollte an dieser Stelle nicht im Vordergrund stehen.

          Besten Dank.

          1. Hallo,

            Eine typografische Diskussion sollte an dieser Stelle nicht im Vordergrund stehen.

            Wäre aber zielführend.

            Gruß
            Kalk

            1. Eine typografische Diskussion sollte an dieser Stelle nicht im Vordergrund stehen.

              Wäre aber zielführend.

              Gruß
              Kalk

              Inwiefern? Würde das etwas am Template ändern? Ich kann euch durch diese kurzen Kommentare nicht folgen.

              1. Hallo,

                Inwiefern?

                Es handelt sich um tatsächlich unterschiedliche Zeichen, nicht um unterschiedliche Bezeichnungen desselben Zeichens. Das sollte dein Script berücksichtigen und einsetzen.

                Gruß
                Kalk

                1. Es handelt sich um tatsächlich unterschiedliche Zeichen, nicht um unterschiedliche Bezeichnungen desselben Zeichens. Das sollte dein Script berücksichtigen und einsetzen.

                  Die Quelldatei wird bei uns aus einer bestimmten Software generiert und besitzt eine sehr fixe Struktur und nur eingeschränkte Zeichen. Aus diesen muss ich versuchen, das Maximum rauszuholen und schicke HTML-Seiten zu basteln. Also kann ich leider nicht einfach sagen, dass es einen Unterschied zwischen Binde- und Gedankenstrich in der Quell-XML gibt, da er syntaktisch nicht vorhanden ist.

                  Daher erneut meine Frage vom ersten Posting: Wie kann man mit den regex die verschiedenen Fälle filtern, um die Ausgabe dementsprechend anzupassen. Ob die Ausgabe später einen Binde- oder Gedankenstrich (&ndash;) enthält, ist leicht umzusetzen. Mein Problem ist eher die vorhergehende Analyse.

  2. Hallo Janine,

    Mein Problem ist nun, beides zusammenzupacken. Wenn ich alles in ein Template schreibe (mit der Variablen "secChange"), wird meine Gedankenstrich-Variable dennoch übergangen. Habt ihr eine Ahnung, warum? Oder gibt es eine elegantere Möglichkeit?

    Probiere es so (ohne Garantie auf Abdeckung aller – außer den genannten – möglichen Fälle):

    <xsl:template match="//text">
      <root>
    
        <xsl:variable name="fstChange">
          <xsl:analyze-string select="." regex="-(\s|\n)([A-Z])">
            <!-- &#xa;| -->
            <xsl:matching-substring>-<xsl:value-of select="regex-group(2)"/>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
              <xsl:value-of select="."/>
            </xsl:non-matching-substring>
          </xsl:analyze-string>
        </xsl:variable>
    
        <xsl:variable name="secChange">
          <xsl:analyze-string select="$fstChange" regex="-(\s|\n|\s)(and|und|oder|or )?">
            <xsl:matching-substring>
              <xsl:choose>
                <xsl:when test="regex-group(2) = 'und'">- und</xsl:when>
                <xsl:when test="regex-group(2) = 'oder'">- oder</xsl:when>
                <xsl:when test="regex-group(2) = 'and'">- and</xsl:when>
                <xsl:when test="regex-group(2) = 'or'">- or</xsl:when>
                <xsl:otherwise/>
              </xsl:choose>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
              <xsl:value-of select="."/>
            </xsl:non-matching-substring>
          </xsl:analyze-string>
        </xsl:variable>
    
        <xsl:variable name="finalChange">
          <xsl:analyze-string select="$secChange" regex="(\s|\n)-">
            <xsl:matching-substring>
              <xsl:value-of select="regex-group(1)"/>- <xsl:value-of select="regex-group(2)"/>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
              <xsl:value-of select="."/>
            </xsl:non-matching-substring>
          </xsl:analyze-string>
        </xsl:variable>
    
        <xsl:value-of select="$finalChange"/>
    
      </root>
    </xsl:template>
    

    Grüße, Thomas

    1. Hallo Thomas,

      besten Dank für dein Template, es funktioniert für die Testfälle super! Jetzt muss ich nur noch verstehen, was du da gemacht hast ;)

      Die Variable finalChange kann man auch so definieren:

      <xsl:variable name="finalChange">
        <xsl:analyze-string select="$secChange" regex="(\s|\n)-">
          <xsl:matching-substring> - </xsl:matching-substring>
          <xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
        </xsl:analyze-string>
      </xsl:variable>
      

      Viele Grüße, Janine