McSaesch Geschrieben 12. April 2017 Geschrieben 12. April 2017 Servus, ich versuche seit ein paar Stunden folgendes Problem per regex zu lösen.... aber ich komm nicht auf die Lösung. Bsp Input String: <frame><id>1</id></frame><frame><id>2</id></frame><frame><id>2</id></frame> Mit dem regulären Ausdruck möchte ich folgende 3 Gruppen (Matches) finden 1)<frame><id>1</id></frame> 2)<frame><id>2</id></frame> 3)<frame><id>3</id></frame> Folgenden Ausdruck habe ich: "<frame>.+</frame>" Wie kann ich nun angeben, dass es zwischen den frame-Tags keine weiteren frame-Tags geben darf? Grüße Zitieren
Crash2001 Geschrieben 12. April 2017 Geschrieben 12. April 2017 (bearbeitet) Indem du nicht den Punkt verwendest, sondern (ich gehe davon aus, dass das immer so stehen soll wie 1), 2) und 3), oder?) sondern Prüfung, ob der gesamte String passt: (<frame><id>[0-9]*<\/id><\/frame>)* Prüfung auf Substring: <frame><id>[0-9]*<\/id><\/frame> Die "/" müssen maskiert werden mit "\" davor. Gehen die Zahlen höher als 9, dann muss pro Stelle mehr noch ein ? zusätzlich dort hin. (Fragezeichen = 0 oder 1 beliebige Ziffer Bearbeitet 12. April 2017 von Crash2001 Zitieren
goepp Geschrieben 12. April 2017 Geschrieben 12. April 2017 (bearbeitet) /<frame>.+?<\/frame>/g / muss maskiert werden. Schau dir mal den Unterschied zwischen greedy und non-greedy (?) bei regex an und was Flags (g) bedeuten. Bearbeitet 12. April 2017 von goepp Zitieren
Whiz-zarD Geschrieben 12. April 2017 Geschrieben 12. April 2017 Wieso willst du überhaupt ein XML-Dokument mit Regulären Ausdrücken parsen? JimTheLion reagierte darauf 1 Zitieren
McSaesch Geschrieben 12. April 2017 Autor Geschrieben 12. April 2017 (bearbeitet) Danke für die schnelle Antwort, aber leider funktioniert das nicht wie erhofft. Mit der Antwort von goepp bekomme ich keinen Match.Success, mit dem Bsp von Crash2001 wird nur der erste frame-Tag <frame>...</frame> erkannt, aber nicht die anderen beiden. Mein Bsp. private void Sample() { string test = @"<frame><id>1</id></frame><frame><id>2</id></frame><frame><id>3</id></frame>"; //Regex reg = new Regex(@"/<frame>.+?<\/frame>/g"); Regex reg = new Regex(@"<frame><id>[0-9]*<\/id><\/frame>"); Match curMatch = reg.Match(test); List<string> results = new List<string>(); if (curMatch.Success) { for (int i = 0; i < curMatch.Groups.Count; i++) { string xml = curMatch.Groups[i].Value; } } } Ich bekomme n frame Elemente als Antwort. Zusätzlich kann es sein, dass der Stream auch unvollständige frame Elemente enthält. Also will ich per Regex nur die vollständigen frame Elemente aus dem string parsen. Für die Gegebenheiten erschien mit Regex als passende Lösung. Bearbeitet 12. April 2017 von McSaesch Zitieren
goepp Geschrieben 12. April 2017 Geschrieben 12. April 2017 (bearbeitet) <frame>.+?<\/frame> Dann lass mal den / am Anfang und den /g am Ende weg. Zum testen: http://regexr.com/3fnsb Bearbeitet 12. April 2017 von goepp Zitieren
McSaesch Geschrieben 12. April 2017 Autor Geschrieben 12. April 2017 Treffer!! Besten Dank, auch für die Seite, jetzt hab ich was zum testen. Zitieren
McSaesch Geschrieben 12. April 2017 Autor Geschrieben 12. April 2017 vor 12 Minuten schrieb McSaesch: Treffer!! Besten Dank, auch für die Seite, jetzt hab ich was zum testen. Ok, zu früh gefreut. Laut der Seite zum Testen, wird alles korrekt erkannt. Teste ich das ganze dann im Code, wird nur das erste frame - Element erkannt.... Zitieren
JimTheLion Geschrieben 12. April 2017 Geschrieben 12. April 2017 http://stackoverflow.com/a/1732454/3595565 Würde das Problem mit XPath angehen. XML: <root> <frame> <frame></frame> <id> 1 </id> </frame> <frame> <id> 2 </id> </frame> <frame> <id> 2 </id> </frame> </root> XPath: /root/frame[count(.//frame) = 0] Würde dann die frame-Nodes mit den ids 2 als Ergebnis geben, weil beim ersten ja weitere frame-tags zwischen den frame-tags vorhanden sind. Wie soll das Ergebnis eigentlich aussehen? Das was ich da gemacht habe fühlt sich ziemlich geraten an. Zitieren
Whiz-zarD Geschrieben 12. April 2017 Geschrieben 12. April 2017 (bearbeitet) Meine Frage, wieso du überhaupt das Ganze mit regulären Ausdrücken versuchst, hast du auch nicht beantwortet. Das .Net-Framework bietet dir schon möglichkeiten, ein XML-Dokument zu parsen. Wozu das Rad neu erfinden? Edit: Dein Problem ist, dass du die Match()-Methode aufrufst. Das gibt dir aber nur ein Ergebnis zurück. Du musst die Matches()-Methode aufrufen. Bearbeitet 12. April 2017 von Whiz-zarD Zitieren
goepp Geschrieben 12. April 2017 Geschrieben 12. April 2017 my $xml = "<frame><id>1</id></frame><frame><id>2</id></frame><frame><id>3</id></frame>"; while($xml =~ /(<frame>.+?<\/frame>)/g){ print "$1\n"; } In Perl klappt das so wunderbar. <frame><id>1</id></frame> <frame><id>2</id></frame> <frame><id>3</id></frame> Zitieren
Whiz-zarD Geschrieben 12. April 2017 Geschrieben 12. April 2017 (bearbeitet) Schön, dass es in Perl klappt ... Das Problem ist nicht der reguläre Ausdruck. Er hat einfach die falsche Methode verwendet. Bearbeitet 12. April 2017 von Whiz-zarD Zitieren
McSaesch Geschrieben 12. April 2017 Autor Geschrieben 12. April 2017 Dank des Hinweises auf Matches läufts! Besten Dank! Der Input String kommt von einem Gerät, mit dem man per XML Schnittstelle kommunizieren kann. Die Antworten kommen nur als Fragmente, nicht als vollständige XML Dokumente, d.h. ich müsste die Antworten erst mal in eine XML Struktur packen. Also bekomme ich einen xml ähnlichen Stream zurück, aus dem ich mir die Antwort-Fragmente per Regex rausparse. Wenn jemand nen besseren Weg kennt, ich bin ganz Ohr. Erst mal danke für die Infos, es läuft jetzt. Zitieren
Whiz-zarD Geschrieben 12. April 2017 Geschrieben 12. April 2017 Wie sehen denn die Fragmente aus? Zitieren
McSaesch Geschrieben 13. April 2017 Autor Geschrieben 13. April 2017 (bearbeitet) Morgens Wie schon beschrieben: <frame><id>1</id>...beliebig weitere tags </frame> Als Antwort können beliebig viele frame Tags kommen. Bearbeitet 13. April 2017 von McSaesch Zitieren
Whiz-zarD Geschrieben 13. April 2017 Geschrieben 13. April 2017 (bearbeitet) Im Grunde ist es doch ein vollständiges XML-Dokument. Du bekommst halt nicht nur eins, sondern mehrere. Der Wurzelknoten ist halt <frame>. Nun kommt es halt auf den Kontext drauf an, was du mit den Daten vorhast. Wenn die XML-Struktur vorgegeben ist, könnte man dann den XmlSerializer verwenden und aus dem XML-Dokument ein POCO-Objekt erzeugen. [XmlRoot("frame")] public class Frame { [XmlElement("id")] public int Id { get; set; } } string xml = "<frame><id>1</id></frame>"; XmlSerializer serializer = new XmlSerializer(typeof(Frame)); Frame frame = (Frame)serializer.Deserialize(new StringReader(xml)); Um einfach über alle Kind-Elemente im Wurzelknoten zu iterieren kann man auch ein XDocument verwenden: string xml = "<frame><id>1</id></frame>"; XDocument xDoc = XDocument.Parse(xml); foreach(XElement element in xDoc.Root.Descendants()) { Console.WriteLine($"{element.Name} -> {element.Value}"); } Ein XDocument lässt sich auch mittels Linq Filtern. Eine weitere Möglichkeit, um Abfragen auf XML-Dokumenten abzusetzen wäre XPath und der XPathNavigator: string text = "<frame><id>1</id></frame>"; XPathDocument docNav = new XPathDocument(new StringReader(text)); XPathNavigator nav = docNav.CreateNavigator(); XPathNodeIterator nodes = nav.Select("//frame/*"); while (nodes.MoveNext()) { Console.WriteLine($"{nodes.Current.Name} -> {nodes.Current.Value}"); } XPath ist eine vom W3C entwickelte Abfragesprache für XML-Dokumente. Eine Dokumentation findest du auch im Wikipedia-Artikel. Viele Wege führen nach Rom aber ich halte die Lösung mit regulären Ausdrücken eine der schlechtesten. Das ist sehr fehleranfällig, denn was passiert, wenn dazwischen irgendwo mal ein Leerzeichen oder ein Zeilenumbruch ist? Damit muss dein Ausdruck auch klar kommen können, denn das ist ja kein Fehler. Auch sind reguläre Ausdrücke schlecht lesbar. Ich denke mal, du selbst wirst den regulären Ausdruck binnen kürzester Zeit nicht mehr verstehen und muss erst mal wieder nachschauen, was der bedeutet. XML-Dokumente einlesen ist ein gelöstestes Problem und warum sollte man sich wieder selbst eine Lösung ausdenken? Selbst das .Net-Framework bietet hier sogar mehrere Lösungen an. Das Framework bietet mit der XmlDocument-Klasse sogar noch eine vierte Variante. Bearbeitet 13. April 2017 von Whiz-zarD pr0gg3r und stefan.macke reagierten darauf 2 Zitieren
stefan.macke Geschrieben 13. April 2017 Geschrieben 13. April 2017 vor einer Stunde schrieb Whiz-zarD: Viele Wege führen nach Rom aber ich halte die Lösung mit regulären Ausdrücken eine der schlechtesten. Als kleine Ergänzung, warum das so ist: http://stackoverflow.com/questions/590747/using-regular-expressions-to-parse-html-why-not Zitieren
Tician Geschrieben 24. April 2017 Geschrieben 24. April 2017 Für die Zukunft hätte ich auch die Seite anzubieten, die hat mir immer besonders gut gefallen: https://regex101.com/ Also zum Regex Testen^^ Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.