[SOLVED]QXmlStreamReader !



  • hi,

    i have in my application to convert, to a graphic item, this XML code :

    @
    <place id="cId175-i943123747">
    <name>
    <text>FORK_1</text>
    <graphics>
    <offset x="22" y="-10"/>
    </graphics>
    </name>

    <graphics>
     <position x="500" y="692"/>
    </graphics>
    
    <initialMarking>
     <text>1</text>
     <graphics>
      <offset x="22" y="20"/>
     </graphics>
    </initialMarking>
    

    </place>
    @

    i tray like this :

    @
    QXmlStreamReader xmlreader(&recordfile);
    QXmlStreamAttributes attributes;

    while (!xmlreader.atEnd()) {
    xmlreader.readNextStartElement();

    if(xmlreader.isStartElement()){
    if(xmlreader.name() == "place")
    {
    attributes = xmlreader.attributes();
    QStringRef id = attributes.value("id");
    qDebug()<<id;
    xmlreader.readNextStartElement();
    if(xmlreader.name() == "name")
    {
    xmlreader.readNextStartElement();
    if(xmlreader.name() == "text")
    {
    qDebug()<<xmlreader.readElementText ();
    }
    }
    }
    }
    }
    @

    how to make the code more simple ? any suggestion ?



  • You can try to use QDomDocument.



  • how to make the code more simple ? any suggestion ?

    What do you mean by simpler? I'm not sure to understand what you want to achieve with the shown snippet.

    If your XML file has a well-defined structure, I would implement a readPlace function, which would then call a set of functions, each of them reading a tag content...

    If you want to get access to the information contained in the XML later on and repeatedly, then the QDomDocument suggestion is a good point.



  • The XML file uses an XML schema :

    the only disadvantage of QDomDocument resides in the fact that it occupies a huge memory space, since all the XML file (XML tree) will be loaded at once in the memory. But it's simple for implementation !

    bq. Johan wrote : If you want to get access to the information contained in the XML later on and repeatedly, then the QDomDocument suggestion is a good point.

    I didn't understand the difference here between QDomDocument and QXmlStreamReader ?

    thanks. :)



  • bq. Johan wrote : If you want to get access to the information contained in the XML later on and repeatedly, then the QDomDocument suggestion is a good point.

    I didn't understand the difference here between QDomDocument and QXmlStreamReader ?

    Well, if you have some piece of information in the XML which has to be accessed from various places at different times, QDomDocument may more appropriate in the sense that it allows easier access to the wanted data than QXmlStreamReader, which has to walk through the whole file each time.

    From what you wrote I think you got the difference between the two methods (QDomDocument and QXmlStreamReader) quite well.

    According to the XML file you gave as an example, I would write a function readPlace, which would be called each time the <place> tag is called, and my first guess is that it would look like the snippet you provided in your first post. But again I'm not sure to understand what you mean by "simpler"...



  • With both QDomDocument and QXmlStreamReader, i will get a huge function (readPlace) code.
    This is the implementation using QDomDocument :

    @
    void PNetTab::readPlaces (QDomNodeList nodlist)
    {
    QString id, name;
    int offsetx, offsety, x, y, initmark;
    QVariant v;

    for(int i=0; i<nodlist.size() ; i++)
    {
    QDomNode nod = nodlist.at(i);

    //place id
    QDomNamedNodeMap attrs = nod.attributes ();
    

    id = attrs.namedItem ("id").nodeValue () ;

    //get child elements
    QDomNodeList childs = nod.childNodes ();
    for(int k=0; k<childs.size() ; k++)
     {
    

    QDomNode childnod = childs.at(k);
    //<name>
    if(childnod.nodeName() == "name")
    {
    QDomNodeList namechilds = childnod.childNodes ();
    for(int j=0; j<namechilds.size() ; j++)
    {
    QDomNode child = namechilds.at(j);
    if(child.nodeName() == "text")
    {
    name = child.toElement().text();
    }
    if(child.nodeName() == "graphics")
    {
    QDomNodeList grahicschilds = child.childNodes ();
    for(int p=0; p<grahicschilds.size() ; p++)
    {
    QDomNode child = grahicschilds.at(p);
    if(child.nodeName() == "offset")
    {
    v.setValue(child.toElement().attribute("x"));
    offsetx = v.toInt();
    v.setValue(child.toElement().attribute("y"));
    offsety = v.toInt();
    }
    }
    }
    }
    }
    //<graphics>
    if(childnod.nodeName() =="graphics")
    {
    QDomNodeList childs = childnod.childNodes ();
    for(int p=0; p<childs.size() ; p++)
    {
    QDomNode child = childs.at(p);
    if(child.nodeName() == "position")
    {
    v.setValue(child.toElement().attribute("x"));
    x = v.toInt();
    v.setValue(child.toElement().attribute("y"));
    y = v.toInt();
    }
    }
    }
    if(childnod.nodeName() == "initialMarking")
    {
    QDomNodeList childs = childnod.childNodes ();
    for(int p=0; p<childs.size() ; p++)
    {
    QDomNode child = childs.at(p);
    if(child.nodeName() == "text")
    {
    v.setValue(child.toElement().text());
    initmark = v.toInt();
    }
    }
    }
    }
    Place * place = new Place(id, name, offsetx, offsety, x, y, initmark);
    scene->addItem(place);
    }

    }
    @

    So, by simpler I meant : is there a magic solution to reduce the lines of code ?
    or it's an inevitable situation ?



  • I don't think there is a magic solution, at least I don't see any.
    What I could suggest is to split the code in smaller functions, which will be easier to maintain and debug.



  • I think I know what you mean :-) Few days ago I ended up with 170 lines in a single function which did heavy parsing, with lots of conditions based on attribute names, values, etc (I managed to trim it down to 60 lines).

    As Johan suggests, you can split your parsing task in several functions. For example, when your parser reaches an element you want to process, you could create a separate function with the streamer as a parameter
    @
    processFooElement(QXmlStreamReader &xmlreader)
    @

    Something like that.



  • @issam

    I have created a sample program that parses the xml file using QXmlStreamReader , have a look at "XmlStreamReader":http://www.mediafire.com/?gagl2jngb87b3qg. Currently it can parse the xml file that provided in the first post, you can extend it as per your requirement.



  • This is it Sam ! You are my rescuer ;)

    bq. Johan wrote : If your XML file has a well-defined structure, I would implement a readPlace function, which would then call a set of functions, each of them reading a tag content…

    You are right Johan ! Now, I think that the magic solution is the rule : divide to reign.
    Well, I always use this rule in programming. But, because this is my first contact with XML I was so confused that I forget it ! But, Sam in his masterpiece program use it professionally !

    Now, I have a ready XML parser for my application which uses QXmlStreamReader. So I think that I have an other reason to use QXmlStramReader instead of QDomDocument. I will kick out this last ! :)

    @Sam : I have used an QXmlSchemaValidator to validate the XML file against an XML schema. Thus, I will eliminate some lines of your XmlParser class's code such as :

    @
    else
    {
    qDebug() << "XML-Pseudocode type mismatch";
    break;
    }
    }else
    {
    //log error
    qDebug() << "Unknown Token received : " << xml.name().toString();
    continue;
    }
    @

    What do you think ?

    thank all you guys :)



  • [quote author="issam" date="1366937188"]
    @Sam : I have used an QXmlSchemaValidator to validate the XML file against an XML schema. Thus, I will eliminate some lines of your XmlParser class's code .
    [/quote]

    You are welcome :)

    You can extend it as per your requirement , However i didnt use QXmlSchemaValidator for any of my xmlParsers may be i'll implement it now.

    In case you need any help, feel free to ask.



  • thank you very much for your interest and kindness, Sam !


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.