Jump to content

Empfohlene Beiträge

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

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

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

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
/<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

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

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

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
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....

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

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.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

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

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen
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>

 

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

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.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

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

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Nimm an der Diskussion teil

Du kannst jetzt hier posten und Dich später registrieren. Wenn Du bereits über eine Konto verfügst, melde Dich jetzt an, um mit Deinem Konto zu posten.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

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

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

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


Fachinformatiker.de, 2019 SE Internet Services

fidelogo_small.png

if_icon-6-mail-envelope-closed_314900.pnSchicken Sie uns eine Nachricht!

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

Fachinformatiker.de App


Get it on Google Play

Kontakt

Hier werben?
Oder senden Sie eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...

Wichtige Information

Fachinformatiker.de verwendet Cookies. Mehr dazu in unserer Datenschutzerklärung