Qt: как использовать QtXmlstreamreader для чтения строк данных массива из файла xml - PullRequest
0 голосов
/ 18 марта 2020

Я пытаюсь загрузить все данные 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"

Ответы [ 2 ]

0 голосов
/ 19 марта 2020

Я нашел решение проблемы. По-видимому, пока проблема l oop.

заключается в следующем:

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;
    }

}
0 голосов
/ 19 марта 2020

На основе следующего примера: QXmlStreamReader для анализа XML в 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"))
...