Laden...

HTML Code Parsen

Erstellt von MasterOfCoding vor 19 Jahren Letzter Beitrag vor 18 Jahren 5.379 Views
M
MasterOfCoding Themenstarter:in
131 Beiträge seit 2004
vor 19 Jahren
HTML Code Parsen

Hallo!

Ich habe eine HTML-Tabelle, welche ich in eine ListView übertragen will (siehe Anhang).
Die Tabelle beginnt bei "<!-- Supplierungen Begin -->" und endet bei "<!-- Supplierungen Ende -->" und die Anzahl der Zeilen kann dann bei Laufzeit immer variieren.

Meine Probleme bei dieser Sache: Ich habe keine Ahnung, wie ich das am besten machen soll.

Ich bekomme die ganze HTML-Datei als einzelnen String (durch einen WebResponse).

In Delphi habe ich schon einmal so etwas Ähnliches gemacht, aber da hatte ich die HTML-Datei dann in einer TStringList, sodass ich Alles Zeile für Zeile in einer for-Schleife durchgehen konnte.

Wie ich dann den Text zwischen den Tags herausbekommen soll weiß ich überhaupt nicht und wie ich es dann am klügsten und effektivsten in die Listview übertrage.

mfg
Andy

PS: Mein Nickname hat nicht unbedingt was mit meinen Fähigkeiten zu tun. 😁

1.373 Beiträge seit 2004
vor 19 Jahren

Wenn der HTML Code den XHTML-Regeln folgt, kannst du ihn doch als XML parsen. Da gibt es ja genug Unterstütztung seitens .NET.

MfG VizOne

M
329 Beiträge seit 2004
vor 19 Jahren

tut er nicht, wenn ich das richtig sehe...
nunja, du kannst nach de strings <!-- Supplierungen Begin --> resp Ende suchen mit string.IndexOf("teststring"); und dann einen substring machen.

Das würde dir die arbeit schon ein wenig erleichtern.

1.373 Beiträge seit 2004
vor 19 Jahren

Oder natürlich Regular Expressions.

MfG VizOne

M
MasterOfCoding Themenstarter:in
131 Beiträge seit 2004
vor 19 Jahren

Das mit dem SubString ist schon mal eine sehr gute Idee. Danke.

Aber wie soll ich dann weiter vorgehen? Soll ich Zeile für Zeile (die Zeilenenden kann ich ja mit IndexOf heraussuchen) alles durchgehen?

Und mein größtes Problem: Wie bekomme ich die Daten aus den Tags heraus?
Außerdem würde mich interessieren ob ihr vorher alles parsen würdet und dann erst in die ListView einfügen, oder das einfügen in die ListView ganz in parsen einbauen?

Mit Regular Expressions kenn ich mich leider überhaupt nicht aus.

mfg,
Andy

PS: Ich wünschte es wäre XML, XHTML, oder ein Webservice den man mittels SOAP erreicht. Aber das Leben ist hart... 😉

S
127 Beiträge seit 2004
vor 19 Jahren

also ich würde das mit Regularen Ausdrücken such was ich will

hier ein Link zu einem anderen Forumsbeitrag

ich hoffe das dir das helfen kann

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo MasterOfCoding,

und um noch zu ergänzen, wenn du dich jetzt in RE einarbeitest, hast du dein ganzes Programmierleben was davon!

herbivore

C
1.215 Beiträge seit 2004
vor 19 Jahren

dem kann ich nur zustimmen!
regex erleichtert die die arbeit ganz ungemein.

sicherlich ist schlau geschriebenes parsen per stringfunktionen oder durchlauf in einem char-array die performanteste methode - aber es dauert eben auch locker 5x solange an zeitaufwand was die programmierarbeit betrifft...
😉

grtz
chief

P
939 Beiträge seit 2003
vor 19 Jahren

Ich habe mal schnell einen Performanztest zum Vergleichen von Regex mit String.IndexOf geschrieben.

class RegexVsIndexOf {

	static void Main(string[] args) {

		int count = 2000000;
		Regex indexOfRegex = new Regex("Test", RegexOptions.Compiled);

		string text = "Das ist ein etwas längerer Text. " +
				  "Irgendwo kommt das Wort Test drinnen vor.";

		CodeTimer codeTimer = CodeTimer.GetByName("codeTimer");
		codeTimer.Start();
		for(int i = 0; i < count; i++) {
			int index = indexOfRegex.Match(text).Index;
		}
		codeTimer.Stop();
		Console.WriteLine("Regex: " + codeTimer.TimeString + " s");

		codeTimer.Reset();
		codeTimer.Start();
		for(int i = 0; i < count; i++) {
			int index = text.IndexOf("Test");
		}
		codeTimer.Stop();
		Console.WriteLine("IndexOf: " + codeTimer.TimeString + " s");
	}
}

Ergebnis:

Regex:   00:01:796 s
IndexOf: 00:03:984 s

Man sieht, selbst im einfachsten aller möglichen Fälle ist ein Regex schon schneller. Dürfte sehr schwierig sein, einen Regex mit eigenem Code zu schlagen. Besonders, wenn das Problem komplizierter wird.

Ist eigentlich merkwürdig. Warum wird IndexOf dann nicht mit einem Regex implementiert? ... Frage schon selbst beantwortet ... weil der erst kompiliert werden müsste was schon wieder länger dauert.

Gruss
Pulpapex

Ps: Bevor jemand fragt, CodeTimer ist meine eigene Klasse.

M
MasterOfCoding Themenstarter:in
131 Beiträge seit 2004
vor 19 Jahren

Hallo!

Ich habe mich unterdessen weiterhin mit diesem parsing-problem beschäftigt.

Ich muss ehrlich gestehen, dass ich mit Regulären Ausrücken absolut nicht auskenne und leider aufgrund der Schule auch nicht Zeit habe um mich damit zu beschäftigen.

Aber ich habe mittels Internet jetzt einen anderen Lösungsansatz ermittelt.
Ich habe mshtml.tlb mit meinem Projekt refernziert und versuche nun MSHTML nützen.

Ich bekomme hier auch den Inhalt der Tabelle, aber eben alles in einer Wurst (Das hat dann ungefähr so ausgesehen, nur viel länger: DATUM KL. ST. VERTR. FACH RAUM STATT STATT BEMERKUNG MO 21.06.04 5C).
Nun frage ich mich, ob es vielleicht möglich wäre, das ganze sogar Zeilenweise oder Tagweise auszulesen. Ich komme nämlich leider mit dem MSHTML noch nicht ganz zurecht. Vielleicht könnt ihr mir helfen meinen Code etwas zu optimieren.

private void button1_Click(object sender, System.EventArgs e)
		{
		   IHTMLDocument2 doc = new HTMLDocumentClass();  //MSHTML initialisieren
		   doc.write(new object[] {MyHTML});  //MyHTML ist vom typ string
		   doc.close();
		   foreach(IHTMLElement el in (IHTMLElementCollection)doc.body.all)
		   {
				if (el.tagName == "TABLE")
				{
					listBox1.Items.Add(el.innerText);
					break;  //Die erste Tabele ist gefunden ich kann aufhören zu suchen
				}
		   }
		}

Außerdem würde ich gerne wissen:

  1. Ist es eine gute Idee den MSHTML-Parser zu verwenden, oder soll ich doch besser Reguläre Ausdrücke verwenden (in diesem Fall würde ich um etwas code bitten, da ich mich damit nicht auskenn)?
  2. Muss ich den MSHTML parser dann auch wieder freigeben? So viel ich weiß ist das ja kein managed code, sodass der Garbage Collector doch nicht funktioniert.
  3. Kann ich direkt MSHTML die Datei herunteladen lassen, oder muss ich den zu parsenden Code mit doc.Write(...) selbst hinzufügen?

Vielen Dank für eure Hilfe,
Andreas

P
939 Beiträge seit 2003
vor 19 Jahren

Du solltest beim MSHTML-Parser bleiben, meine Meinung.

Einen Html-Parser mit Regexes oder sonst wie, selbst zu schreiben, ist ein extremer Aufwand. Es gibt tausende von Sonderregeln, die beachtet werden müssen und der Parser muss auch bei fehlerhaftem Html robust reagieren.
Der System.Xml-Namespace ist auch nicht geeignet, da ja in Html viel mehr erlaubt ist was in Xml einen Fehler darstellt. Wahrscheinlich kann ein Xml-Parser die meisten Html-Dokumente nicht einlesen (obwohl ich es nicht ausprobiert habe, solltest du vielleicht mal testen).

Zu 2. Guck mal nach ob es eine Dispose-Methode gibt.
Zu 3. Kann ich nichts zu sagen. Durchstöber die Methoden ob sich eine geeignete findet. Kann aber sein, dass die mshtml.tlb nur zum Parsen und Formatieren gedacht ist.

Gruss
Pulpapex

Ps: in der Java-Klassenbibliothek gibt Klassen speziell zum Html-Parsen. Da hat man es leichter.

M
MasterOfCoding Themenstarter:in
131 Beiträge seit 2004
vor 18 Jahren

Hallo!

Ich will jetzt, wenn möglich bei MSHTML bleiben, allerdings stoße ich bei der Benutzung auf Probleme.

Hiermit versuche ich die Daten aus der Tabelle rauszubekommen:


		   IHTMLDocument2 doc = new HTMLDocumentClass();
		   doc.write(new object[] {MyHTML});
		   doc.close();
		   foreach(IHTMLElement el in (IHTMLElementCollection)doc.body.all)
		   {
				if (el.tagName == "TD")
				{
					//Die Datei wird nicht gefüllt mit el.innerText (Datei bleibt leer):
					StreamWriter sw = new StreamWriter(@"C:\test.txt");
					sw.Write(el.innerText);
					sw.Close()
					MessageBox.Show(el.innerText);  //Das funktioniert seltsamerweise schon
					//Das funktioniert nicht (bekomme folgende Exception:
                                        //Exception-Klasse System.ArgumentNullException mit der Meldung 'Value cannot be null.'):
					listBox1.Items.Add(el.innerText);
				}
		   }
		}

MyHTML ist natürlich vom Typ String. Im Anhang findet ihr noch einmal die HTML-Datei. Das Problem ist, dass die Datei leer bleibt, obwohl ich doch das Zeug hineinschreibe.

Danke für die Hilfe,
Andy