XmlStreamReader aborting with Expected character data.



  • Trying to parse an XML file and placing the elements on a tree widget. I'm only getting the 1st three lines parsed before the reader aborts. The beginning of the XML is:

    <?xml version="1.0" encoding="UTF-8"?>
    <export version="D">
      <design>
        <source>path to source file</source>
    ...
    There's a lot more below this
    

    The <design> tag is successfully being added to the tree widget, but the parser aborts immediately after with:

    Error Type: 1 
    Error String: "Expected character data." 
    Line Number: 3 
    Column Number: 10 
    Char. Offset: 70
    

    What's puzzling me about this is the <export> tag and its data is apparently being overlooked during the parsing, and that line 3, column 10 is the closing ">" for the <design> tag, however, that tag does successfully get added to the tree widget.

    Could someone explain exactly what's happening here ?
    Thanks in advance !

    <date>Fri 07 Apr 2017 04:13:15 PM CDT</date>


  • Which OS are you using? Could you give us a typical path?

    On windows separator is \, which might cause troubles as the following character will be "eaten".



    • Could you make sure the XML file is valid with something like http://www.xmlvalidation.com/ ?
    • Could you post the code you are using to read the xml?


  • @JohanSolo Running Ubuntu 14.04.
    @VRonin The XML is generated by KiCad. The link you posted reports no errors found.

    Core reader code:

    while (!xmlReader.atEnd()) {
            QXmlStreamReader::TokenType token = xmlReader.readNext();
    
            if (token == QXmlStreamReader::StartDocument) {
                ui->value_XmlVersion->setText(xmlReader.documentVersion().toString());
                ui->value_XmlEncoding->setText(xmlReader.documentEncoding().toString());
                continue;
            } // end isStartDocument
    
            if (token == QXmlStreamReader::StartElement) {
                if (debugMain) qDebug() << "xmlStreamReader(): Detected StartElement.";
    
                treeAddParent(xmlReader.qualifiedName().toString());
    
                QXmlStreamReader::TokenType parent = token;
    
                while (!QXmlStreamReader::EndElement) {
                    if (debugMain) qDebug() << "xmlStreamReader(): Reading until an EndElement is detected...";
                    token = xmlReader.readNext();
                    temp = xmlReader.qualifiedName().toString();
                    treeAddChild(parent, temp);
                } // end while !EndElement
    
            } // end if isStartElement
    
            continue;
    
        } // end reading xmlSourceFile
    
        xmlSourceFile.close();
    
    Error Trap code:
        ```
    // xmlReader error trap
        if (xmlReader.hasError()) {
            qDebug() << "   Error Type:" << xmlReader.error();
            qDebug() << " Error String:" << xmlReader.errorString();
            qDebug() << "  Line Number:" << xmlReader.lineNumber();
            qDebug() << "Column Number:" << xmlReader.columnNumber();
            qDebug() << " Char. Offset:" << xmlReader.characterOffset();
            xmlSourceFile.close();
        } // end xmlReader error trap
    

    Code to add a parent node to the tree widget:

    void window_Main::treeAddParent(QString name) {
        QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeSourceFile);
    
        if (debugMain) qDebug() << "treeAddParent(): Setting tree item text to" << name;
        treeItem->setText(0, name);
    
        if (debugMain) qDebug() << "treeAddParent(): Adding" << name << "item to tree...";
        ui->treeSourceFile->addTopLevelItem(treeItem);
        if (debugMain) qDebug() << "treeAddParent(): Item added to tree.";
    }
    

    Code to add a child node to the tree widget:

    void window_Main::treeAddChild(QXmlStreamReader::TokenType token, QString name) {
        QTreeWidgetItem *treeItem = new QTreeWidgetItem();
    
        if (debugMain) qDebug() << "treeChild(): Setting tree item text to" << name;
        treeItem->setText(0, name);
    
        if (debugMain) qDebug() << "treeAddChild(): Adding" << name << "item to tree...";
        ui->treeSourceFile->addTopLevelItem(treeItem);
    
        if (debugMain) qDebug() << "treeAddChild(): Item aded to tree.";
    }
    

    The Application Output window shows:

    "----------" 
    xmlStreamReader(): Detected StartElement. 
    treeAddParent(): Setting tree item text to "design" 
    treeAddParent(): Adding "design" item to tree... 
    treeAddParent(): Item added to tree. 
    "----------" 
       Error Type: 1 
     Error String: "Expected character data." 
      Line Number: 3 
    Column Number: 10 
     Char. Offset: 70
    

    The code doesn't appear to get back to the point of "continuing to read until an endElement" is detected before bombing-out.

    Thanks !



  • I don't like this forum software ! It's chopping-up code blocks !
    Reposting Core Reader Code:

    while (!xmlReader.atEnd()) {
            QXmlStreamReader::TokenType token = xmlReader.readNext();
    
            if (token == QXmlStreamReader::StartDocument) {
                ui->value_XmlVersion->setText(xmlReader.documentVersion().toString());
                ui->value_XmlEncoding->setText(xmlReader.documentEncoding().toString());
                continue;
            } // end isStartDocument
    
            if (token == QXmlStreamReader::StartElement) {
                if (debugMain) qDebug() << "xmlStreamReader(): Detected StartElement.";
    
                treeAddParent(xmlReader.qualifiedName().toString());
    
                QXmlStreamReader::TokenType parent = token;
    
                while (!QXmlStreamReader::EndElement) {
                    if (debugMain) qDebug() << "xmlStreamReader(): Reading until an EndElement is detected...";
                    token = xmlReader.readNext();
                    temp = xmlReader.qualifiedName().toString();
                    treeAddChild(parent, temp);
                } // end while !EndElement
    
            } // end if isStartElement
    
            continue;
    
        } // end reading xmlSourceFile
    
        xmlSourceFile.close();
    


  • @grpace said in XmlStreamReader aborting with Expected character data.:

    Error Type: 1 
     Error String: "Expected character data." 
      Line Number: 3 
    Column Number: 10 
     Char. Offset: 70
    

    What's puzzling me about this is the <export> tag and its data is apparently being overlooked during the parsing, and that line 3, column 10 is the closing ">" for the <design> tag, however, that tag does successfully get added to the tree widget.

    According to this stackoverflow post, the mentioned error might come from trying to read the text of an empty element, i.e. using readElementText() on <export> for instance.



  • @JohanSolo The code, while apparently ignoring the <export version=...>, gets past that and does add <design> to the tree. This is a KiCad-generated XML for a circuit board and net list. There are a lot of nested elements in it.



  • @grpace said in XmlStreamReader aborting with Expected character data.:

    @JohanSolo The code, while apparently ignoring the <export version=...>, gets past that and does add <design> to the tree. This is a KiCad-generated XML for a circuit board and net list. There are a lot of nested elements in it.

    I just stumbled across this potential source of problem: if by chance you're trying to access the text data of an element only containing elements (I can't remember the name of such nodes), then you'll most probably get the error you reported on your first post.



  • @JohanSolo Thank you.
    I just looked at the post you referenced and I saw it yesterday... That post is from 2010 !
    Also, the post is using hard-coded if statements:

    if (name == "firstname" || name == "surname" || 
                name == "email" || name == "website")
            {
                cout << "element name: '" << name  << "'" 
                             << ", text: '" << xml.readElementText() 
                             << "'" << endl;
            }
    

    I cannot hard-code things like that... KiCad could change things at any time and the reader code would break.

    What would be the work-around ?

    Thanks so much for your help !



  • @grpace said in XmlStreamReader aborting with Expected character data.:

    while (!QXmlStreamReader::EndElement)

    This is a constant. either is always executed or never (in this case never)

    To read arbitrarily deep trees recursion is necessary. see an example of converting an xml into a tree model here: https://github.com/VSRonin/Qt-Model-Serialisation/blob/dev/xmlmodelserialiser.cpp#L196 and https://github.com/VSRonin/Qt-Model-Serialisation/blob/dev/xmlmodelserialiser.cpp#L71



  • @JohanSolo Here is another excerpt from the XML:

    <components>
      <comp ref="D5">
        <value>LED</value>
        <footprint>LEDs:LED_D10.0mm</footprint>
        <libsource lib="device" part="LED"/>
        <sheetpath names="/" tstamps="/"/>
        <tstamp>58D2AD94</tstamp>
      </comp>
    ....
    

    XML continues until the </components> tag, with each <comp>...</comp> describing a particular component on the circuit board. This will absolutely change with each circuit design. No hard-coding any values will work.



  • @VRonin Thank you for the links. However, I notice several QStringLiterals in the code. I cannot rely on any literal text strings being present anywhere in the XML.



  • @grpace said in XmlStreamReader aborting with Expected character data.:

    I cannot rely on any literal text strings being present anywhere in the XML.

    I use them because depending on the constant I do different things. You just have to do the same thing to all elements so you do not need them



  • There does appear to be an issue with the QXmlStreamReader::readElementText(). I had this in a qDebug() section:

    if (debugMain) {
                qDebug() << "    Token Type:" << xmlReader.tokenType();
                qDebug() << "  Token String:" << xmlReader.tokenString();
                qDebug() << "          Name:" << xmlReader.name();
                qDebug() << "Qualified Name:" << xmlReader.qualifiedName();
                qDebug() << "  Element Text:" << xmlReader.readElementText();
            }
    

    The readElementText() line was causing the bomb-out. I commented-out that line and can successfully read to the end of the file.


Log in to reply
 

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