PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : QRegExp inhalt von Tags



dml
06-09-2009, 16:33
Hi,

ich versuche schon seit über einen Monat einen Weg zu finden, wie ich aus
einem Dokument mit den Tags:


<html>
...
<body>
...
<TR><TD><zutat>Möhre</zutat></TD></TR>
<TR><TD><zutat>Kartoffel</zutat></TD></TR>
<TR><TD><zutat>Zwiebel</zutat></TD></TR>
<TR><TD><zutat>1...n</zutat></TD></TR>
...
</body>
</html>


die Zutaten in eine Stringlist bekomme.
Mein Hauptversuch dabei war:



QRegExp exp;
exp.setPattern(".*<zutat>(.*)</zutat>.*");
exp.exactMatch(str);


doch es klappt einfach nicht, egal was ich mache.
Deshalb wollte ich Euch um Eure Hilfe bitten.

vielen Dank! :)
grüße
dml

locus vivendi
06-09-2009, 17:10
Qt Regexe habe ich noch nie verwendet, aber zwei Dinge kommen mir seltsam vor, erstens, das du exactMatch verwendest und nicht die "Index"-Funktionen und zweitens beginnt dein Ausdruck schon mit Punkt-Sternchen, was bedeutet ein beliebiges Zeichen beliebig oft zu matchen. Mit anderen Worten, jeden String. Das kommt mir nicht richtig vor.

dml
06-09-2009, 17:29
Ja, ich habe es auch schon mit


while ((pos = exp.indexIn(str_recipe, pos)) != -1) {
categories << exp.cap(1);
qDebug()<<endl<<" exp.cap(1)="<<exp.cap(1);
pos += exp.matchedLength();
}


versucht.
Doch entweder er schreibt die gesamte html Datei hinnein, oder er findet das Ende nicht.
Wenn ich nur eine einzige Zutat habe, funktioniert es wunderbar, nur ab zwei funktioniert es nicht mehr.

Ansonsten weiß ich leider nicht was ich anstatt des .* verwenden kann, da es ja undefiniert ist.

undefined
06-09-2009, 17:57
Dafür gibt es QDomDocument oder QXmlQuery, damit ist das ein klacks ;)


QXmlQuery query;
query.setQuery("doc('index.html')/html/body/TABLE/TR/TD/zutat[1]");

locus vivendi
06-09-2009, 18:01
Ok, das mit dem .* am Anfang klappt sogar, wußte ich gar nicht, so selten wie ich Regexe verwende.

Ist aber auch unnötig, wenn du QRegExp::indexIn verwendest.

Andererseits, .* als Captured Subexpression wird bestimmt nicht funktionieren, wenn du mehrere Tags einzeln matchen möchtest. Denn dann fängt er mit dem ersten Tag an, captured alle mittleren und hört erst mit dem letzen auf. Wenn du dich in der Subexpression auf weniger Zeichen beschränkst, dann sollte es funktionieren.

Hier mal Code, der bei mir funktioniert:
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <ostream>
#include <vector>

#include <stdlib.h>

#include "QtCore/QRegExp"
#include "QtCore/QString"
#include "QtCore/QStringList"

int main()
{
std::ifstream infile("qt_regex_data.txt");
if(!infile)
{
std::cerr << "Failed to open input file!\n";
return EXIT_FAILURE;
}

std::vector<char> v;
std::copy(std::istreambuf_iterator<char>(infile.rdbuf()), std::istreambuf_iterator<char>(), std::back_inserter(v) );
if(!infile)
{
std::cerr << "Failed to read all input!\n";
return EXIT_FAILURE;
}
v.push_back('\0');

std::cout << "Data:\n" << v.data() << "\n-------------------\n";

QString instring(QString::fromLatin1(v.data()) );

QRegExp regex("<zu>([a-zA-z \\d]*)</zu>");
//QRegExp regex("<zu>(.*)</zu>");

if(regex.exactMatch(instring) )
{
std::cout << "Complete String matches.\n";
return 0;
}

int idx = 0;
while((idx = regex.indexIn(instring, idx)) != -1)
{
std::cout << "Match at offset " << idx << " of length " << regex.matchedLength()
<< ", captured = " << regex.capturedTexts().at(1).toLatin1().data() << ".\n";
idx += regex.matchedLength();
}
}

---------------------------------------------

und Test Daten:
<zu>abc</zu>
klsaf
<zu>xy</zu>
b
------------------------------------------------

Geht das?

dml
06-09-2009, 18:21
exp.setPattern("<zutat>([\\w\\s]+)</zutat>");

hat geholfen.
Vielen dank locus vivendi! :)
Auch Dir undefined, bitte nicht sauer sein, wenn ich mal ein wenig fauler bin. ;)

Vielen Dank, ich saß wirklich lange an diesem Problem.