Zum Inhalt springen

Empfohlene Beiträge

Geschrieben

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

Geschrieben (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 von Crash2001
Geschrieben (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 von goepp
Geschrieben (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 von McSaesch
Geschrieben
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....

Geschrieben

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.

Geschrieben (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 von Whiz-zarD
Geschrieben
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>

 

Geschrieben

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.

Geschrieben (bearbeitet)

Morgens

Wie schon beschrieben:

<frame><id>1</id>...beliebig weitere tags </frame>

Als Antwort können beliebig viele frame Tags kommen.

Bearbeitet von McSaesch
Geschrieben (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 von Whiz-zarD
  • 2 Wochen später...

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...