Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Parser für BBcode?
Golo Roden
myCSharp.de - Member

Avatar #avatar-2167.png


Dabei seit:
Beiträge: 4.207
Herkunft: Riegel am Kaiserstuhl

Themenstarter:

Parser für BBcode?

beantworten | zitieren | melden

Hallo,

kennt jemand eine Komponente für .NET, die mir einen Parser für BBcode bereitstellt? Sprich, ich rufe sie mit einem String auf, der entsprechenden Code enthält, und erhalte entsprechendes HTML zurück.

Wäre schön, wenn jemand so etwas kennt ...

Viele Grüße,


der Eisbär
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Der Eisbär,

BBCode in HTML umzusetzen ist doch fast ein Job für RegEx, BB ist ja in den meisten Fällen schon so gut wie HTML (z.B. => <b>). Das einzige, was man von Hand machen muss, ist die Klammerung prüfen.

herbivore
private Nachricht | Beiträge des Benutzers
Golo Roden
myCSharp.de - Member

Avatar #avatar-2167.png


Dabei seit:
Beiträge: 4.207
Herkunft: Riegel am Kaiserstuhl

Themenstarter:

beantworten | zitieren | melden

Hi herbivore,

joa, so weit ist das sicher kein Problem ... ich möchte aber auch prüfen, ob ein Dokument gültig ist, sprich nicht so Sachen wie ungültig verschachtelte Tags enthält, dass jedes öffnende auch ein schließendes Tag hat, ...

Und da wird's dann schon komplizierter ... oder?

Viele Grüße,


der Eisbär
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Der Eisbär,

nö, würde ich nicht sagen. Bei BB ist es ja gerade erlaubt, nicht korrekt zu schachteln. Deshalb wurde auch das im letzten Artikel (und auch das in diesem :-) nur deshalb wie von mir beabsichtlich dargestellt, weil ich eben das schließende Tag weggelassen habe.

herbivore
private Nachricht | Beiträge des Benutzers
Golo Roden
myCSharp.de - Member

Avatar #avatar-2167.png


Dabei seit:
Beiträge: 4.207
Herkunft: Riegel am Kaiserstuhl

Themenstarter:

beantworten | zitieren | melden

Hallo,

okay, dann sollte ich vielleicht noch dazu sagen, dass die Ausgabe in XHTML erfolgen soll und zumindest DAS valide sein muss ;-).

Viele Grüße,


der Eisbär
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Der Eisbär,

schon klar, genau das habe ich auch mit dem "Das einzige, was man von Hand machen muss, ist die Klammerung prüfen" gemeint. Ich sehe schon ein, dass es das eine Ecke komplizierter macht, als einfach n RegEx.Replace drüberlaufen zu lassen. Wäre aber mal ein schönes Einsatzgebiet für die Klasse Stack, die man sonst nie braucht. :-)

herbivore
private Nachricht | Beiträge des Benutzers
Golo Roden
myCSharp.de - Member

Avatar #avatar-2167.png


Dabei seit:
Beiträge: 4.207
Herkunft: Riegel am Kaiserstuhl

Themenstarter:

beantworten | zitieren | melden

Hallo herbivore,

okay, dann reden wir doch vom gleichen :-) .... hmmm, also wie gesagt, ne fertige Komponente dafür wäre schick, weil eigentlich würde ich mich gerne um das Coden von so nem Parser drumrumdrücken ... andererseits wäre es natürlich mal eine Herausforderung ;-).

Da ich nicht sehr viel Ahnung von diesem Thema habe - wie geht man prinzipiell an so eine Analyse eines Textes ran, um die Tags und deren Attribute und deren Verschachtelung zu ermitteln?

Viele Grüße,


der Eisbär
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Der Eisbär,

ich würde per RegEx.Match/NextMatch-Schleife mit dem Pattern (?<bbtag>\[\s*(?<close>/?)\s*(?<tagname>)[a-zA-Z]+)(?<attribute>[^\]]+?)\s*\])) über den Text laufen und und gucken, ob m.Groups["tagname"] ein gültiger Tagname ist. Wenn ja und wenn m.Groups["close"] leer ist, kommt das Tag auf den Stack. Wenn m.Groups["close"] nicht leer ist, guckst du, ob das oberste Tag (case insensitive) mit m.Groups["tagname"] gleich ist. Wenn ja, hast du ein Tag-Paar gefunden. Wenn nicht kannst du entweder das schließende Tag verwerfen oder den Stack solange abräumen, bis du das passende öffnende Tag gefunden hast.

Das ist jetzt so runtergeschrieben und muss sicherlich im Detail korrigert werden.

Von den gefundenen paarigen Tags kennst du die ja dank der Match-Klasse die Position und kannst an dieser gezielt substituieren, wobei du noch ggf. m.Groups["attribute"] berücksichtigen musst.

Naja, so in der Art müsste es gehen.

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 885
Herkunft: Hessen

beantworten | zitieren | melden

Der Eisbär:

Ich meine sowas schonmal gesehen zu haben bei codeproject.

Offtopic:
herbivore verdienst du eigentlich auch Geld bzw. schläfst du auch mal? Woher dein ganzes Wissen? Egal in welchem Thread ich schaue, du redest immer mit und lieferst Klasse Beiträge - Fazination pur. *neidisch bin*
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo -acid-,

danke für die Blumen. Falls deine Fragen nicht nur rhetorisch gemeint waren: Im moment arbeite ich gerade nine-to-five, deshalb schreibe ich momentan auch tagsüber fast gar nichts. Geld gibt es dafür auch (nicht fürs Beiträge schreiben - das wäre fein - sondern fürs Arbeiten). Aber im Prinzip versuche ich nicht mehr als 3-4 Monate im Jahr zu arbeiten. Und ja, ich schlafe täglich (oder besser nächtlich), habe ich mir noch nicht abgewöhnen können. Zu guter Letzt: Mein Wissen kommt aus etlichen Jahren Beschäftigung mit Informatik. Am meisten lernt man übringens, wenn man so früh wie möglich beginnt, Anderen etwas beizubringen.

herbivore


PS: @Eisbär: Hast du mit meinem Entwurf etwas anfangen können?
private Nachricht | Beiträge des Benutzers
DeveloperX
myCSharp.de - Member



Dabei seit:
Beiträge: 462
Herkunft: .at/ooe&stmk

beantworten | zitieren | melden

Hallo!

Da ich mich gerade in RegEx einarbeite und ein nützliches Tool dafür gefunden habe, poste ich mal den Link: The RegEx Coach

Damit kann man reguläre Ausdrücke, in Echtzeit austesten, also ohne vorher was kompilieren zu müssen. Bin mir zwar nicht sicher, ob die Ausdrücke dann genauso in .NET verwendet werden können, weil ich nicht weis, ob reguläre Ausdrücke standardisiert sind?!

mfg DeveloperX
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo DeveloperX,

die Basics von RE sind über die verschiedenen Sprachen und Systeme hinweg relativ gleich. Aber im Detail gibt es dann schon jede Menge Unterschiede.

herbivore

PS: Mit On-the-fly Regex-Tester: Regex-Lab gibt es ein Tool, das die Regex-Syntax von .NET verwendet.
private Nachricht | Beiträge des Benutzers
LastGentleman
myCSharp.de - Member

Avatar #avatar-1696.jpg


Dabei seit:
Beiträge: 1.274
Herkunft: Österreich

auch was in Deutsch

beantworten | zitieren | melden

Hei hab auch was zu Regular Expressions, auf Deutsch

ich poste mal den URL, weils gerade dazu passt.

http://www.sql-und-xml.de/regex/index.html
"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein
private Nachricht | Beiträge des Benutzers
elron
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Berlin

beantworten | zitieren | melden

@herbivore
na wow muss mich auch gerade damit rumschlagen!
will lieber in meiner ADS weiter Programmieren X(

also cooler post nur meine While ist endlos naja whatever!
das ganze sieht so aus!

"[bold]bla1 bla1[/bold]cdata[bold]bla2 bla2[/bold]";
regExpression = \[bold\]([^\]]+)\[\/bold\]
result =
m.Groups.Count 0--[bold]bla2 bla2[/bold]
m.Groups.Count 1--bla2 bla2

was ich hier vermisse ist den zweiten treffer er wertet mir nur den ersten vorkommen aus aber nicht den zweiten! mit NextMatch() bekomme ich den zweiten treffer! aber wie soll ich das schreiben habe kein Beispiel gefunden!

versucht habe ich es mit While(m.Success) eine endlosschleife kam raus. kann mir das jemand weiterhelfen ?

Voran danke,
Elron
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo elron,


m = Regex.Match (...);
while(m.Success) {
   // ...
   m = m.NextMatch ();
}
Allerdings bekommt du mit deinem Pattern Probleme mit geschachtelten Tags, denn

[bold]bla1 [italic]bla1[/italic][/bold]

würde ja wegen der ']' zwischen den bold-Tags nicht matchen, abgesehen davon, dass ']' auch so im Text auftauchen kann:

[bold]siehe [1][/bold]

herbivore
private Nachricht | Beiträge des Benutzers
elron
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Berlin

beantworten | zitieren | melden

@herbivore
danke für dein Post jetzt läuft es man da hätte ich auch selber drauf kommen können! ähmm du hast recht mit deinem Beispiel ich hoffe das ich den RegA.
noch anpassen kann..

Gruß
Elron
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo elron,

mit

\[bold\](.*?)[\/bold\]

oder vielleicht noch besser

\[bold\](([^\[]+)([(?!/bold))*([^\[]+))[\/bold\]

solltest du zu einem [bold] das nächste, schließende [/bold] finden (ungetestet).

Allerdings gibt es auch hier ein Problem. Bei

[bold]bla1[bold]bla2[/bold]bla2[/bold]

wird auf

[bold]bla1[bold]bla2[/bold]

gematcht.

Deshalb funktioniert mein Vorschlag oben auch mit einer Kombination von RegEx (für einzelne Tags) und Stack.

herbivore
private Nachricht | Beiträge des Benutzers
elron
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Berlin

beantworten | zitieren | melden

@herbivore
ja das Porb. habe ich auch bei meinem RegEx.
Habe es erstmal so umgesetzt!
z.B.
string:

"Hallo [em]Mustermann[/em] wie geht es [-b]dir?[/-b] Ich hoffe [-b][em] gut?[/em][/-b]" ("-" wegen konvertierung) auf myCSharp.de


public string FinalQuadCode(string FindQuadCode)
    {
        Dictionary<string, string> myDic = new Dictionary<string, string>();
        myDic.Add("Bold", @"\[b\](?<content>.*?)\[\/b\]");
        myDic.Add("Cursive", @"\[em\](?<content>.*?)\[\/em\]");
        
        foreach (KeyValuePair<string, string> myEn in myDic)
        {
            Match m = null;
            Regex r = null;

            r = new Regex(myEn.Value);
            m = r.Match(FindQuadCode);
            if (m.Success)
            {
                while (m.Success) 
                {
                    if (myEn.Key == "Bold")
                    {
                        FindQuadCode = FindQuadCode.Replace(m.Groups[0].Value, "<b>" + m.Groups["content"] + "</b>");
                    }
                    if(myEn.Key == "Cursive")
                    {
                        FindQuadCode = FindQuadCode.Replace(m.Groups[0].Value, "<em>" + m.Groups["content"] + "</em>");
                    }
                    m = m.NextMatch();
                }
            }
            else
            {
                
            }
        }
        return FindQuadCode;
    }

gut sicherlich kann man es noch um längen besser schreiben oder anpassen!
was meinst du?

Oder so ist es noch besser!


public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			this.textBoxOut.Text = ConvertString(this.textBoxIn.Text);
		}

		private static Regex rex = new Regex("\\[(?<tag>[^\\]]*)\\](?<innerText>.*?)\\[\\/\\k<tag>]", RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.Singleline);

		string ConvertString(string value)
		{
			StringBuilder convertedString = new StringBuilder(value.Length);
			int lastMatchLastIndex = -1;
			foreach (Match m in rex.Matches(value))
			{
				// Anfang/Letzter Index bis Match übernehmen
				if (lastMatchLastIndex == -1) lastMatchLastIndex = 0;
				convertedString.Append(value.Substring(lastMatchLastIndex, (m.Index - lastMatchLastIndex)));

				string tag = m.Groups["tag"].Value.ToLower();
				string innerText = m.Groups["innerText"].Value;
				lastMatchLastIndex = m.Index + m.Length;
				
				switch (tag)
				{
					case "b":
					case "i":
					case "u":
						// Gültiger Tag
						convertedString.Append("<" + tag + ">");
						convertedString.Append(ConvertString(innerText));
						convertedString.Append("</" + tag + ">");
						break;
					
					default:
						// Ungültiger Tag, nur Inhalt übernehmen
						convertedString.Append(ConvertString(innerText));
						break;
				}
			}

			if (lastMatchLastIndex == -1)
			{
				// Nichts gefunden, alles kopieren
				convertedString.Append(value);
			}
			else
			{
				// restliche Zeichen übernehmen
				convertedString.Append(value.Substring(lastMatchLastIndex));
			}
			return convertedString.ToString();
		}
	}

Gruß
Elron
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo elron,

naja, der Code bzw. die Regex haben eben die schon benannten Schwächen, für die oben ich eine Lösungsmöglichkeit aufgezeigt hatte.

Der Ansatz mit dem Dictionary gefällt mich nicht schlecht. Da er allerdings nicht ausreicht, weil du drei Informationen benötigst, und er dich für die dritte Information zu einem if in der Schleife zwingt, verliert er allerdings deutlich an Eleganz.

Ich denke du erreichst das gleiche einfacher mit:


Regex.Replace (FindQuadCode, "[b](?<content>.*?)[/b]", "<b>${content}</b>");
Ansonsten ist mit noch aufgefallen, dass du b und em mixt. Zu b gehört i und zu em gehört strong.

HTH

herbivore
private Nachricht | Beiträge des Benutzers
elron
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Berlin

beantworten | zitieren | melden

@herbivore
jo das sieht doch schon besser aus!
danke dir für deine hilfe!

Gruß
Elron
private Nachricht | Beiträge des Benutzers
DeveloperX
myCSharp.de - Member



Dabei seit:
Beiträge: 462
Herkunft: .at/ooe&stmk

beantworten | zitieren | melden

Hallo!

Auf der Suche nach BBCode-Parsern bin ich nun fündig geworden und habe ein (anscheinend) gutes Tutorial gefunden. Ist allerdings auf PHP basierend, dürfte jedoch nicht so schwer sein, es umzuschreiben.

zonik´s tutorials

mfg
private Nachricht | Beiträge des Benutzers
alf468
myCSharp.de - Member



Dabei seit:
Beiträge: 196

beantworten | zitieren | melden

Irgendwie verstehe ich die Geschichte mit RegEx nicht richtig X(

Wäre nett wenn du mal ein kleines Beispiel machen könntest
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo alf468,

ich meine das nicht böse, ich bin nur etwas verwundert:

Was meinst du mit Beispiel? Ich habe einen Algorithmus beschrieben. Es stehen sogar die wesentlichen Codeelemente drin. Was willst du mehr? Soll das jetzt ausprogrammieren oder wie stellst du dir das vor?

herbivore
private Nachricht | Beiträge des Benutzers
alf468
myCSharp.de - Member



Dabei seit:
Beiträge: 196

beantworten | zitieren | melden

Sicher du hast das schon klar beschrieben aber irgendwie geht das bei mir nicht so richtig.

string str = " [bold] jjkljk [/bold]";
            string patt = @" (?<bbtag>\[\s*(?<close>)\\?\s*(?<tagname>)[a-zA-Z]+)(?<attribute>[^\]]+?)\s*\] ";
            Regex r = new Regex(patt, RegexOptions.IgnoreCase);

            Match m = r.Match(str);
            while (m.Success)
            {
                Console.WriteLine(m.Groups["tagname"].ToString());
                m = m.NextMatch();
            }
            Console.ReadLine();

Es wird da schon nix ausgegeben
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo alf468,

hm, naja, da hat der Pattern halt noch nicht ganz gestimmt. Das war ja nur ein Beispiel (also genau was du wolltest ;-). An der Stelle sollte der ganz normale Prozess der Fehlersuche beginnen.

Ich mache das immer so, dass ich den Pattern verkürze, bis er matcht. Dann verlängere ich ihn wieder, bis er nicht mehr matcht. An dem Teil, den ich im letzten Schritt hinzugefügt habe, muss also ein Fehler sein, also korrigieren. Und dann wieder verlängern. Das Ganze solange bis es passt.

Verkürzen kann man natürlich nicht an beliebigen Stellen und man muss darauf achten, dass die Klammerung immer noch passt.

@"(?<bbtag>\[\s*(?<close>/?)\s*(?<tagname>[a-zA-Z]+)\s*(?<attribute>[^\]]*?)\s*\])"

herbivore
private Nachricht | Beiträge des Benutzers
alf468
myCSharp.de - Member



Dabei seit:
Beiträge: 196

beantworten | zitieren | melden

Wenn ich das habe kann ich ja mit string.Replace(..) die Tags umwandeln.
Aber ich möchte ganz gerne auch die Code Tags verwenden und in innerhalb von Code darf der BBCode nicht umgewandelt werden.
Wie kann ich da am besten vorgehen ?
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo alf468,

sehe nicht, wo du da String-Replace brauchst. Alles was du brauchst sollte mit m.Index, m.Length und String.Substring gehen.

herbivore
private Nachricht | Beiträge des Benutzers
alf468
myCSharp.de - Member



Dabei seit:
Beiträge: 196

beantworten | zitieren | melden

Aber dann müsste ich den Index einmal verändern und alle weiteren Tags würden nicht mehr passen.

Wenn das Programm in der m.Success Schleife ist und bei einem gefundenen Paar eine Änderung an dem original String vorgenommen wird stimmt doch der Index für die anderen Tags nicht mehr.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo alf468,

wieso müsstest du den Index verändern? Und warum sollte es notwendig sein, den Original-String zu verändern? Du parst den Original-String in der Schleife und per m.Index, m.Length und String.Substring (zusammen mit StringBulder) baust du das Ergebnis zusammen. Wenn du innerhalb von
 keine Ersetzungen durchführen willst, zwingt dich ja keiner.

herbivore
private Nachricht | Beiträge des Benutzers
alf468
myCSharp.de - Member



Dabei seit:
Beiträge: 196

beantworten | zitieren | melden

Kann sein das ich mich jetzt total dumm anstelle aber irgendwie verstehe ich das nicht.
Ich habe den Index und die Länge vom Start- und Endtag. Damit kann ich ohne Probleme die Tags umwandeln aber wie bekomme ich das wieder in den Text ?
private Nachricht | Beiträge des Benutzers