0

我有很多非标准化的 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"

实现这一目标的最可靠和最稳定的方法是什么?

4

1 回答 1

1

通常,您不能使用正则表达式来解析诸如 HTML 之类的上下文无关语法——任何计算自动机理论教科书都会准确地告诉您这一点。

那么你在这里有什么选择呢?有几个:

  • 使用Qt WebKit 的 DOM API来操作页面,然后将其烘焙回 HTML。这里最大的缺点是 QtWebKit 已被弃用,并且不会在未来的 Qt 版本中出现。
  • 使用 Qt WebEngine 或 Qt WebKit 并使用 Javascript 操作 DOM。如果您了解 Javascript,这是一个很好的选择,因为它是 100% 可移植的,并且 Javascript 是专门为此类任务而设计的。缺点是如果 HTML 中已经包含 Javascript,它可能会自行操作页面。您尝试使用正则表达式所做的一切都可以使用jQuery 选择器来完成。
  • 使用第三方库(TidyLib 或 libxml2 都应该工作)将 HTML 转换为 XHTML,然后使用 Qt 的内置SAX 解析器读取 XHTML 文档,并且只写出您想要保留的标签。这种方法的优点是它非常轻量级,并且可以在 WebEngine 和 WebKit 不可用的移动和嵌入式平台上工作。缺点是您只剩下 XHTML,这可能是也可能不是您想要的。

多年来,我使用了所有这些方法,但现在最后一种方法是最有效的。也就是说,如果实现时间是您最关心的问题,只需用 Javascript 编写内容,就可以省去麻烦。

于 2015-12-06T19:52:28.523 回答