C++ Qt:无法分析某些svg项目样式

C++ Qt:无法分析某些svg项目样式,c++,xml,qt,svg,xml-parsing,C++,Xml,Qt,Svg,Xml Parsing,我正在尝试显示和修改一些svg,我希望能够阅读或修改它们的颜色 GraphicsColorSvgItem::GraphicsColorSvgItem(QString svgContent, QGraphicsItem *parent) : QGraphicsSvgItem(parent), _svgXML() { _svgXML.setContent(svgContent); setSharedRenderer(new QSvgRenderer(_svgXML.t

我正在尝试显示和修改一些svg,我希望能够阅读或修改它们的颜色

GraphicsColorSvgItem::GraphicsColorSvgItem(QString svgContent, QGraphicsItem *parent) :
    QGraphicsSvgItem(parent),
    _svgXML()
{
    _svgXML.setContent(svgContent);
    setSharedRenderer(new QSvgRenderer(_svgXML.toByteArray()));
}

void GraphicsColorSvgItem::setColor(QColor c)
{
    changeAttributes("fill", c.name().toUpper());
    changeAttributes("stroke", c.name().toUpper());
    changeAttributes("style", c.name().toUpper());   // this obviously needs to be treated separately just don't know how
    renderer()->load(_svgXML.toByteArray());
}

void GraphicsColorSvgItem::changeAttributes(QString attName, QString attValue)
{
    QDomElement rootElem = _svgXML.documentElement();
    QDomNode n = rootElem.firstChild();
    while(!n.isNull())
    {
        if(n.isElement())
        {
            QDomElement e = n.toElement();
            QSTRING_DEBUG(e.tagName());
            if(e.hasAttribute(attName))
            {
                e.setAttribute(attName, attValue);
            }
            if(n.hasChildNodes())
                recursiveChangeAttributes(n.firstChild(), attName, attValue);
        }
        n = n.nextSibling();
    }
}

void GraphicsColorSvgItem::recursiveChangeAttributes(QDomNode node, QString attName, QString attValue)
{
    QDomNode n = node;
    while(!n.isNull())
    {
        if(n.isElement())
        {
            QDomElement e = n.toElement();
            if(e.hasAttribute(attName))
            {
                e.setAttribute(attName, attValue);
            }
            if(n.hasChildNodes())
                recursiveChangeAttributes(n.firstChild(), attName, attValue);
        }
        n = n.nextSibling();
    }
}
以下svg已成功更改为颜色I pass

<!DOCTYPE html>

<svg height="100" width="100">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
  Sorry, your browser does not support inline SVG.  
</svg> 

很抱歉,您的浏览器不支持内嵌SVG。
但是,下面的svg有一个“style”属性——我不知道如何解析它

<!DOCTYPE html>

<svg height="250" width="500">
  <circle cx="50" cy="50" r="40" style="fill:red;stroke:black;stroke-width:3" />
  Sorry, your browser does not support inline SVG.
</svg>

很抱歉,您的浏览器不支持内嵌SVG。
结果显示为黑色-因为整个“样式”设置为不受支持的内容

编辑:现在我正在做一个字符串替换,它似乎工作。。。但我希望有一个xml方法

if(attName=="style")
{
    QString value = e.attribute(attName);
    int fill1 = value.indexOf(QString("fill:")) + 5;
    int fill2 = value.indexOf(QString(";"), fill1);
    if(fill2<=fill1)
       fill2 = value.indexOf(QString("\""), fill1);
    QString subString = value.mid(fill1, fill2 - fill1);
    value.replace(subString, attValue);    
    fill1 = value.indexOf(QString("stroke:")) + 7;
    fill2 = value.indexOf(QString(";"), fill1);
    if(fill2<=fill1)
       fill2 = value.indexOf(QString("\""), fill1);
    subString = value.mid(fill1, fill2 - fill1);
    value.replace(subString, attValue);
    e.setAttribute(attName, value);
}
else
{
    e.setAttribute(attName, attValue);
}
if(attName==“style”)
{
QString值=e.属性(attName);
int fill1=value.indexOf(QString(“fill:”)+5;
int fill2=value.indexOf(QString(;”),fill1);

if(fill2样式属性中的内容通常是CSS样式语法。因此,使用支持CSS的解析器可能是最好的选择。正则表达式可能很有用,但可能不是最容易使用的

话虽如此,我还是想换个话题:

if(attName=="style")
{
    QString value = e.attribute(attName);

    QStringList styleList = value.split(";");
    QStringList newStyleList;
    foreach(QString style, styleList)
    {
        QStringList propertyVal = style.split(":");
        QString prop = propertyVal.first().trimmed();
        QString newVal = propertyVal.at(1).trimmed();
        if(prop == "stroke")
        {
            newVal = attValue;
        }
        else if(prop == "fill")
        {
            newVal = attValue;
        }
        else
        {
            // no changes
        }
        newStyleList.append(prop + ":" + newVal);
    }

    e.setAttribute(attName, newStyleList.join(";"));
}
下面是一个可以工作的正则表达式示例

/fill:(.*?)(?=;|$)/
也就是说:

查找单词
fill
,后跟冒号,然后尽可能少地查找字符,直到找到分号或字符串结尾

在捕获组列表中,第一个组(第0个之后)应包含属性值对值的字符串

然后需要将此表达式放入
QRegularExpression
中,并在字符串上使用

希望有帮助