Qt:如何使用QtXmlstreamreader从xml文件中读取数组数据的字符串

Qt: how to use QtXmlstreamreader to read strings of array data from xml file

我正在尝试将所有 xml 数据加载到 QList 中。 我不确定我从 xml.

获取所有数据的编码是否正确

当我尝试 运行 时,xml 中的某些信息在输出中丢失了。

以下是xml个元素:

<?xml version="1.0" encoding="UTF-8"?>
<CANBUS>
  <SYSTEM ID="PCU">


    <CAN ID="veh Ops Status Lights">
      <ID>1</ID>
      <Length>6</Length>
    </CAN>
    <CAN ID="veh Sensors">
      <ID>2</ID>
      <Length>5</Length>
    </CAN>
    <CAN ID="veh Faults">
      <ID>3</ID>
      <Length>5</Length>
    </CAN>
    <CAN ID="PCM Faults">
      <ID>4</ID>
      <Length>2</Length>
    </CAN>
    <CAN ID="faults">
      <ID>5</ID>
      <Length>4</Length>
    </CAN>
    <CAN ID="Fuel level">
      <ID>6</ID>
      <Length>8</Length>
    </CAN>
    <CAN ID="Speed">
      <ID>7</ID>
      <Length>8</Length>
    </CAN>
    <CAN ID="Engine Hr Req">
      <ID>8</ID>
      <Length>8</Length>
    </CAN>
    <CAN ID="Odo and Trip">
      <ID>9</ID>
      <Length>8</Length>
    </CAN>
    <CAN ID="Trip 2">
      <ID>10</ID>
      <Length>8</Length>
    </CAN>
  </SYSTEM>
  <SYSTEM ID="IOU">
    <CAN ID="Sync Counter">
      <ID>11</ID>
      <Length>2</Length>
    </CAN>
    <CAN ID="IOU1 Engine">
      <ID>23</ID>
      <Length>2</Length>
    </CAN>
    <CAN ID="IOU1 Alive">
      <ID>112</ID>
      <Length>8</Length>
    </CAN>
    <CAN ID="IOU1 PCM Fault">
      <ID>20A</ID>
      <Length>2</Length>
    </CAN>
    <CAN ID="IOU1 IOM Fault">
      <ID>40A</ID>
      <Length>4</Length>
    </CAN>
    <CAN ID="IOU1 UNIT Fault">
      <ID>15C</ID>
      <Length>4</Length>
    </CAN>
  </SYSTEM>
</CANBUS>

代码如下:

DetectionVar.h

public:
    struct CANList
    {
        QString System;
        QString CAN_ident;
        QString ID;
        QString Length;
    };

    CANList DataCAN;

private:    
    //read the data from file
    QXmlStreamReader xmlReader;
    QString filename;
    QList <CANList> can_identity;

DetectionVar.cpp

void DetectionVar::ReadXML()
{
    filename = QCoreApplication::applicationDirPath() + "/" + "CANBus_Data.xml";
    qDebug() << filename;
    QFile f(filename);
    if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug() << "Cannot read file" << f.errorString();
        return;
    }

    xmlReader.setDevice(&f);

    while(!xmlReader.atEnd())
    {
        xmlReader.readNext();

        if (xmlReader.isStartElement())
        {
            if (xmlReader.name() == "CANBUS")
            {
                while(xmlReader.readNextStartElement())
                {
                    if (xmlReader.name()== "SYSTEM" && xmlReader.attributes().hasAttribute("ID"))
                    {
                        DataCAN.System = xmlReader.attributes().value("ID").toString();
                    }
                    else if (xmlReader.name()== "CAN" && xmlReader.attributes().hasAttribute("ID"))
                    {
                        DataCAN.CAN_ident = xmlReader.attributes().value("ID").toString();
                    }
                    else if (xmlReader.name()== "ID")
                    {
                        DataCAN.ID = xmlReader.readElementText();
                    }
                    else if (xmlReader.name()== "Length")
                    {
                        DataCAN.Length = xmlReader.readElementText();
                    }

                    can_identity.append(DataCAN);
                }
            }
        }
    }

    f.close();


    for (int i = 0; i <can_identity.length(); i++ )
    {
        qDebug()<< "System: " + can_identity.at(i).System;
        qDebug()<< "Ident: " + can_identity.at(i).CAN_ident;
        qDebug()<< "ID: " + can_identity.at(i).ID;
        qDebug()<< "Length: " + can_identity.at(i).Length;
    }

}

数据输出:

"System: PCU"
"Ident: "
"ID: "
"Length: "
"System: PCU"
"Ident: veh Ops Status Lights"
"ID: "
"Length: "
"System: PCU"
"Ident: veh Ops Status Lights"
"ID: 1"
"Length: "
"System: PCU"
"Ident: veh Ops Status Lights"
"ID: 1"
"Length: 6"

基于下一个示例:QXmlStreamReader to parse XML in Qt我已经实施了以下解决方案:

class CANListParser{
public:
    static QList<CANList> parserXML(QIODevice *device){
        QList<CANList> can_identity;
        QString system;

        QXmlStreamReader xmlReader;
        xmlReader.setDevice(device);

        while(!xmlReader.atEnd() && !xmlReader.hasError()) {
            QXmlStreamReader::TokenType token = xmlReader.readNext();
            if(token == QXmlStreamReader::StartDocument) {
                continue;
            }
            if(token == QXmlStreamReader::StartElement) {
                if(xmlReader.name() == "CANBUS")
                    continue;
                if(xmlReader.name() == "SYSTEM"){
                    system = xmlReader.attributes().value("ID").toString();
                    continue;
                }
                if(xmlReader.name() == "CAN"){
                    CANList c = parseCANList(system, xmlReader);
                    can_identity << c;
                }
            }
        }
        return can_identity;
    }
private:
    static CANList parseCANList(const QString & system, QXmlStreamReader & xmlReader){
        CANList c;
        c.System = system;
        QXmlStreamAttributes attributes = xmlReader.attributes();
        if(attributes.hasAttribute("ID")) {
            c.CAN_ident = attributes.value("ID").toString();
        }
        xmlReader.readNext();
        while(!(xmlReader.tokenType() == QXmlStreamReader::EndElement &&
                xmlReader.name() == "CAN")) {
            if(xmlReader.tokenType() == QXmlStreamReader::StartElement) {
                if(xmlReader.name() == "ID")
                    c.ID = xmlReader.readElementText();
                if(xmlReader.name() == "Length")
                    c.Length = xmlReader.readElementText();
            }
            xmlReader.readNext();
        }
        return c;
    }
};
can_identity << CANListParser::parserXML(&f);

要观察 qDebug() 以轻松打印结果,必须执行以下操作:

QDebug operator<<(QDebug debug, const CANList &c){
    QDebugStateSaver saver(debug);
    debug.nospace() << '(' << c.System << ", " << c.CAN_ident << ", " << c.ID << ", " << c.Length << ')';
    return debug;
}
qDebug() << can_identity;

输出:

(("PCU", "veh Ops Status Lights", "1", "6"), ("PCU", "veh Sensors", "2", "5"), ("PCU", "veh Faults", "3", "5"), ("PCU", "PCM Faults", "4", "2"), ("PCU", "faults", "5", "4"), ("PCU", "Fuel level", "6", "8"), ("PCU", "Speed", "7", "8"), ("PCU", "Engine Hr Req", "8", "8"), ("PCU", "Odo and Trip", "9", "8"), ("PCU", "Trip 2", "10", "8"), ("IOU", "Sync Counter", "11", "2"), ("IOU", "IOU1 Engine", "23", "2"), ("IOU", "IOU1 Alive", "112", "8"), ("IOU", "IOU1 PCM Fault", "20A", "2"), ("IOU", "IOU1 IOM Fault", "40A", "4"), ("IOU", "IOU1 UNIT Fault", "15C", "4"))

我找到了解决问题的方法。 显然是 while 循环的问题。

解决方法如下:

void DetectionVar::ReadXML()
{
    filename = QCoreApplication::applicationDirPath() + "/" + "CANBus_Data.xml";
    qDebug() << filename;
    QFile f(filename);
    if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug() << "Cannot read file" << f.errorString();
        return;
    }

    xmlReader.setDevice(&f);

    while(!xmlReader.atEnd())
    {
        xmlReader.readNext();

        if (xmlReader.isStartElement())
        {
            if (xmlReader.name() == "CANBUS")
            {

                while(xmlReader.readNextStartElement())
                {
                    if (xmlReader.name()== "SYSTEM" && xmlReader.attributes().hasAttribute("ID"))
                    {
                        DataCAN.System = xmlReader.attributes().value("ID").toString();

                        while(xmlReader.readNextStartElement())
                        {
                            if (xmlReader.name()== "CAN" && xmlReader.attributes().hasAttribute("ID"))
                            {
                                DataCAN.CAN_ident = xmlReader.attributes().value("ID").toString();

                                while(xmlReader.readNextStartElement())
                                {
                                   if (xmlReader.name()== "ID")
                                   {
                                       DataCAN.ID = xmlReader.readElementText();
                                   }

                                   else if (xmlReader.name()== "Length")
                                   {
                                       DataCAN.Length = xmlReader.readElementText();
                                   }
                                }

                                can_identity.append(DataCAN);
                            }

                        }

                    }

                }
            }
        }
    }

    if (xmlReader.hasError())
    {
        qDebug() << "XML Error: " << xmlReader.errorString().data();
    }

    f.close();


    for (int i = 0; i <can_identity.length(); i++ )
    {
        qDebug()<< "System: " + can_identity.at(i).System;
        qDebug()<< "Ident: " + can_identity.at(i).CAN_ident;
        qDebug()<< "ID: " + can_identity.at(i).ID;
        qDebug()<< "Length: " + can_identity.at(i).Length;
    }

}