Как правильно удалить определенные теги HTML или скобки, содержащие текст в QString, с использованием библиотеки Qt?

У меня есть много нестандартного HTML (смешанного с кучей разметки Wiki), в котором мне нужно убрать из него определенные теги и различные скобки.

QRegularExpression не является подходящим инструментом для работы, как показывает простая строка:

myString =
QString("yes<tag par1='x'>no<tag par2='y'>no</tag>no</tag>yes<tag>no</tag>yes")

// Won't work | This matches the first nested </tag>
myString.replace(QRegularExpression("<tag param1='x'>(.+?)</tag>"),"\\1")

// Won't Work | This matches the last </tag>, removing the second "yes"
myString.replace(QRegularExpression("<tag param1='x'>(.+)</tag>"),"\\1")

В идеале я думаю, что лучше всего подойдет функция, в которой вы задаете 5 параметров:

QString stripCustomBrackets(
        QString input,                     // myString
        QRegularExpression openingBracket, // Eg. "<tag>"  or "{{["
        QRegularExpression openingIdentify,// Eg. "<tag par1='x'>"
                        // par1='x' identifies the tag to work with.

        QRegularExpression closingBracket, // Eg. "</tag>" or "]}}"
        QRegularExpression closingIdentify,// Eg. "FooBar</tag>"
                        // Means you only capture tags with FooBar at the end.

        // <tag> keep text if true </tag>
        bool capture = false) {

    QString output;
    if ( /* Number of openingBrackets equally match closingBrackets */ ) {
        if (capture) { 
            /* Do code where you leave the contents in between the brackets */ 
        } else {
            /* Do code where you remove the contents in between the brackets */
        }
        return output;

    } else {
        qDebug() << "Unable to consolidate;" << endl
                 << openingBracket << " count = " << /* count */ << endl
                 << closingBracket << " count = " << /* count */ << endl
                 << "Brackets do not match each other in number.";
        return input;
    }
}
qDebug() << stripCustomBrackets(mystring, 
    QRegularExpression("<tag"),
    QRegularExpression(" par1='x'>"),
    QRegularExpression("</tag>"),
    QRegularExpression(""),
    true);

qDebug() << stripCustomBrackets(mystring, 
    QRegularExpression("<tag"),
    QRegularExpression(" par2='y'>"),
    QRegularExpression("</tag>"),
    QRegularExpression(""),
    false);

qDebug() << stripCustomBrackets(mystring, 
    QRegularExpression("<tag"),
    QRegularExpression(" par[0-9]='[a-z]'>"),
    QRegularExpression("</tag>"),
    QRegularExpression(""),
    false); 

qDebug() << stripCustomBrackets(mystring, 
    QRegularExpression("<tag "),
    QRegularExpression(""),
    QRegularExpression("No</tag>"),
    QRegularExpression(""),
    false); 

_

"yesno<tag par2='y'>no</tag>noyes<tag>no</tag>yes"

"yes<tag par1='x'>nono</tag>yes<tag>no</tag>yes"

"yesyes<tag>no</tag>yes"

"Unable to consolidate;"
"'<tag '    Count = 2"
"'No</tag>' Count = 3"
"Brackets do not match each other in number.";
"yes<tag par1='x'>no<tag par2='y'>no</tag>no</tag>yes<tag>no</tag>yes"

Какой самый надежный и стабильный способ сделать это?

1 ответ

В общем, вы не можете использовать регулярное выражение для анализа неконтекстной грамматики, такой как HTML - любой учебник по теории вычислительных автоматов скажет вам именно это.

Итак, какие у вас есть варианты? Там несколько:

  • Используйте DOM API Qt WebKit для управления страницей, а затем запишите ее обратно в HTML. Самым большим недостатком здесь является то, что QtWebKit устарел и его не будет в будущих версиях Qt.
  • Используйте Qt WebEngine или Qt WebKit и управляйте DOM с помощью Javascript. Это отличный вариант, если вы знаете Javascript, потому что он на 100% переносим, ​​и Javascript был разработан специально для таких задач, как эта. Недостатком является то, что если в HTML уже есть Javascript, он может самостоятельно манипулировать страницей. Все, что вы пытаетесь сделать с помощью регулярных выражений, может быть выполнено с помощью селекторов jQuery.
  • Конвертируйте HTML в XHTML, используя стороннюю библиотеку (TidyLib или libxml2, обе должны работать), затем используйте встроенный синтаксический анализатор QX SAX для чтения в документе XHTML и записывайте только те теги, которые вы хотите сохранить. Преимущество этого подхода в том, что он очень легкий и будет работать на мобильных и встраиваемых платформах, где WebEngine и WebKit недоступны. Недостатком является то, что вы остались с XHTML, который может или не может быть тем, что вы хотите.

Я использовал все эти подходы на протяжении многих лет, но в наши дни последний подход - это самый эффективный. Тем не менее, если время реализации является вашей главной задачей, просто напишите об этом в Javascript и избавьте себя от хлопот.

Другие вопросы по тегам