Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QXmlStreamReader throws error when reading a sub element
Forum Updated to NodeBB v4.3 + New Features

QXmlStreamReader throws error when reading a sub element

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 2 Posters 905 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Aymeric_Qt
    wrote on last edited by
    #1

    Hello everyone,
    I've tried to read an xml file with the QXmlStreamReader (with Qt6) but I always stumble on the same problem:
    the error "Expected character data" is thrown as soon as the first sub element is read.

    Here is an extract of the xml file:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.2.5.RELEASE</version>
    		<relativePath /> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>com.example</groupId>
    	<artifactId>Aapi</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>Aapi</name>
    	<description>Personnal test project</description>
    
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
            etc ...
    

    Here is how I set the QXmlStreamReader:

    QFile pom(pomPath);
        if(!pom.open(QIODevice::ReadOnly))
        {
            qWarning() << "pom.xml could not be opened:" << pom.errorString();
        }
    QXmlStreamReader xmlReader(&pom);
    

    For testing purposes i've tried very simple loop in order to read the entire file:

    while (!xmlReader.atEnd())
    {
            xmlReader.readNextStartElement();
            qDebug() << xmlReader.readElementText();
    }
    

    Will throw: "Expected character data" at line: 5 column: 15

    Or:

    while(xmlReader.readNextStartElement())
    {
            qDebug() << xmlReader.name();
    }
    

    No error thrown but will also stop at modelVersion (line 5).

    Catching errors:

    if (xmlReader.hasError())
    {
        qDebug() << "Error:" << xmlReader.errorString() << "at line:" << xmlReader.lineNumber()
                 << "column:" << xmlReader.columnNumber();
    }
    

    At some point I've thought the problem came from the fact that the modelVersion tag only contains numbers but even if I comment it out, QXmlStreamReader will stop on the next line.

    After reading the documentations and a lot of forum post etc... I'm starting to running out of ideas and still don't understand where the problem is comming from.
    Am I missing something ?

    Thank you for reading.
    Have a nice day.

    JonBJ 1 Reply Last reply
    0
    • A Offline
      A Offline
      Aymeric_Qt
      wrote on last edited by
      #9

      As expected readElementText() cannot read "complete" (tag and content) child elements.

      However it is possible to ignore child element or to get only their content by using QXmlStreamReader::ReadElementTextBehaviour enum as parameter.

      Unfortunately this does not provide a straight forward solution to my problem so I had to found a workaround.

      For example I want to get all the child elements of the project tag (and ignore all grandchildren):

      while (!xmlReader.atEnd())
         {
             QXmlStreamReader::TokenType token = xmlReader.readNext();
             qDebug() << "Next token:" << token << xmlReader.tokenString() << "- at line:" << xmlReader.lineNumber() << "- name:" << xmlReader.name();
             if(token == QXmlStreamReader::StartElement && xmlReader.name() == QString("project"))
             {
                 xmlReader.readNext();
                 while(xmlReader.name() != QString("project"))
                 {
                     xmlReader.readNextStartElement();
                     qDebug() << "- tag:" << xmlReader.name() << "- content:" << xmlReader.readElementText(QXmlStreamReader::SkipChildElements);
                 }
             }
         }
      

      Although it's working it is not very elegant and might not be really reusable (e.g. to get the dependencies in a pom.xml file).

      Thank you for reading.
      Have a nice day.

      1 Reply Last reply
      0
      • A Aymeric_Qt

        Hello everyone,
        I've tried to read an xml file with the QXmlStreamReader (with Qt6) but I always stumble on the same problem:
        the error "Expected character data" is thrown as soon as the first sub element is read.

        Here is an extract of the xml file:

        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0"
        	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        	<modelVersion>4.0.0</modelVersion>
        	<parent>
        		<groupId>org.springframework.boot</groupId>
        		<artifactId>spring-boot-starter-parent</artifactId>
        		<version>2.2.5.RELEASE</version>
        		<relativePath /> <!-- lookup parent from repository -->
        	</parent>
        	<groupId>com.example</groupId>
        	<artifactId>Aapi</artifactId>
        	<version>0.0.1-SNAPSHOT</version>
        	<name>Aapi</name>
        	<description>Personnal test project</description>
        
        	<properties>
        		<java.version>1.8</java.version>
        	</properties>
        
        	<dependencies>
                etc ...
        

        Here is how I set the QXmlStreamReader:

        QFile pom(pomPath);
            if(!pom.open(QIODevice::ReadOnly))
            {
                qWarning() << "pom.xml could not be opened:" << pom.errorString();
            }
        QXmlStreamReader xmlReader(&pom);
        

        For testing purposes i've tried very simple loop in order to read the entire file:

        while (!xmlReader.atEnd())
        {
                xmlReader.readNextStartElement();
                qDebug() << xmlReader.readElementText();
        }
        

        Will throw: "Expected character data" at line: 5 column: 15

        Or:

        while(xmlReader.readNextStartElement())
        {
                qDebug() << xmlReader.name();
        }
        

        No error thrown but will also stop at modelVersion (line 5).

        Catching errors:

        if (xmlReader.hasError())
        {
            qDebug() << "Error:" << xmlReader.errorString() << "at line:" << xmlReader.lineNumber()
                     << "column:" << xmlReader.columnNumber();
        }
        

        At some point I've thought the problem came from the fact that the modelVersion tag only contains numbers but even if I comment it out, QXmlStreamReader will stop on the next line.

        After reading the documentations and a lot of forum post etc... I'm starting to running out of ideas and still don't understand where the problem is comming from.
        Am I missing something ?

        Thank you for reading.
        Have a nice day.

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #2

        @Aymeric_Qt
        For a start, check the return result from readNextStartElement().

        Then try something other than readElementText(). That (tries to) read the whole of the element, do a bit at a time with readNext() or similar.

        Then try your code on some tiny XML.

        Finally, I don't use (or trust) Qt6, don't suppose you can text on Qt5 instead?

        1 Reply Last reply
        0
        • A Offline
          A Offline
          Aymeric_Qt
          wrote on last edited by
          #3

          Hello @JonB,

          Thanks for your reply.

          I have forgot to mention in my first message that indeed readNextStartElement() returns true (and then false which seems normal).

          Concerning readElementText() I have to use it because I want to retrieve the value beteween the tags and readNext only returns the next token type.

          As you suggested I've tried with a much smaller and simpler xml but I encouter the same problems.

          Concerning the version of Qt it is 6.2.0 so I supposed it is a fairly stable version but is it to early to go with Qt 6 yet ?
          As my project is at the very beginning it is not a big deal to redo on Qt5.

          JonBJ 1 Reply Last reply
          0
          • A Aymeric_Qt

            Hello @JonB,

            Thanks for your reply.

            I have forgot to mention in my first message that indeed readNextStartElement() returns true (and then false which seems normal).

            Concerning readElementText() I have to use it because I want to retrieve the value beteween the tags and readNext only returns the next token type.

            As you suggested I've tried with a much smaller and simpler xml but I encouter the same problems.

            Concerning the version of Qt it is 6.2.0 so I supposed it is a fairly stable version but is it to early to go with Qt 6 yet ?
            As my project is at the very beginning it is not a big deal to redo on Qt5.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #4

            @Aymeric_Qt said in QXmlStreamReader throws error when reading a sub element:

            Concerning readElementText() I have to use it because I want to retrieve the value beteween the tags and readNext only returns the next token type.

            The point is to test by using readNext, not your final solution. You are trying to discover where/why you are getting an error.

            Here is the XML I might start from

            <?xml version="1.0" encoding="UTF-8"?>
            <project>
            	<modelVersion>4.0.0</modelVersion>
            </project>
            

            That's what "tiny" means. Does that work for you, no error on readElementText()? Assuming so, build back up toward your desired input.

            A 1 Reply Last reply
            0
            • JonBJ JonB

              @Aymeric_Qt said in QXmlStreamReader throws error when reading a sub element:

              Concerning readElementText() I have to use it because I want to retrieve the value beteween the tags and readNext only returns the next token type.

              The point is to test by using readNext, not your final solution. You are trying to discover where/why you are getting an error.

              Here is the XML I might start from

              <?xml version="1.0" encoding="UTF-8"?>
              <project>
              	<modelVersion>4.0.0</modelVersion>
              </project>
              

              That's what "tiny" means. Does that work for you, no error on readElementText()? Assuming so, build back up toward your desired input.

              A Offline
              A Offline
              Aymeric_Qt
              wrote on last edited by Aymeric_Qt
              #5

              @JonB,

              Yes when I said ' I've tried with a much smaller and simpler xml' this is excactly the xml file I've created (just project and model version tags).
              And readnext() return a 4 (which is QXmlStreamReader::StartElement token type) on line 3
              and then the error occurs: "Expected character data" at line: 3 column: 10".

              JonBJ 1 Reply Last reply
              0
              • A Aymeric_Qt

                @JonB,

                Yes when I said ' I've tried with a much smaller and simpler xml' this is excactly the xml file I've created (just project and model version tags).
                And readnext() return a 4 (which is QXmlStreamReader::StartElement token type) on line 3
                and then the error occurs: "Expected character data" at line: 3 column: 10".

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #6

                @Aymeric_Qt said in QXmlStreamReader throws error when reading a sub element:

                and then the error occurs: "Expected character data" at line: 3 column: 10".

                And then when you call what does the error occur? Please answer clearly. I am trying to determine whether that comes from readNext() or only from readElementText()?

                I said earlier:

                Then try something other than readElementText(). That (tries to) read the whole of the element, do a bit at a time with readNext() or similar.

                A 1 Reply Last reply
                0
                • JonBJ JonB

                  @Aymeric_Qt said in QXmlStreamReader throws error when reading a sub element:

                  and then the error occurs: "Expected character data" at line: 3 column: 10".

                  And then when you call what does the error occur? Please answer clearly. I am trying to determine whether that comes from readNext() or only from readElementText()?

                  I said earlier:

                  Then try something other than readElementText(). That (tries to) read the whole of the element, do a bit at a time with readNext() or similar.

                  A Offline
                  A Offline
                  Aymeric_Qt
                  wrote on last edited by Aymeric_Qt
                  #7

                  @JonB

                  Sorry if my previous message was confusing.
                  The error occurs when the readElementText() is called.

                  @Aymeric_Qt said in QXmlStreamReader throws error when reading a sub element:

                  For testing purposes i've tried very simple loop in order to read the entire file:
                  while (!xmlReader.atEnd())
                  {
                  xmlReader.readNextStartElement();
                  qDebug() << xmlReader.readElementText();
                  }

                  Will throw: "Expected character data" at line: 5 column: 15

                  If I only use readNext() it runs fine to the end of the file without any error.
                  Here is 2 tests I've made:

                  Xml test file:

                  <?xml version="1.0" encoding="UTF-8"?>
                  <project>
                  	<version>thisversion</version>
                  </project>
                  

                  First loop (readNext() - no error):

                  while (!xmlReader.atEnd())
                  {
                          QXmlStreamReader::TokenType token = xmlReader.readNext();
                          qDebug() << "readNext():" << token << "- at line:" << xmlReader.lineNumber();
                  }
                  

                  Console output:

                  readNext(): 2 - at line: 1
                  readNext(): 4 - at line: 2
                  readNext(): 6 - at line: 3
                  readNext(): 4 - at line: 3
                  readNext(): 6 - at line: 3
                  readNext(): 5 - at line: 3
                  readNext(): 6 - at line: 4
                  readNext(): 5 - at line: 4
                  readNext(): 3 - at line: 4
                  

                  Second loop (readElementText() - error):

                  while (!xmlReader.atEnd())
                  {
                          xmlReader.readNext();
                          qDebug() << xmlReader.readElementText();
                  }
                  

                  Console output:

                  ""
                  "\n\t"
                  Error: "Expected character data." at line: 3 column: 10 ()
                  
                  JonBJ 1 Reply Last reply
                  0
                  • A Aymeric_Qt

                    @JonB

                    Sorry if my previous message was confusing.
                    The error occurs when the readElementText() is called.

                    @Aymeric_Qt said in QXmlStreamReader throws error when reading a sub element:

                    For testing purposes i've tried very simple loop in order to read the entire file:
                    while (!xmlReader.atEnd())
                    {
                    xmlReader.readNextStartElement();
                    qDebug() << xmlReader.readElementText();
                    }

                    Will throw: "Expected character data" at line: 5 column: 15

                    If I only use readNext() it runs fine to the end of the file without any error.
                    Here is 2 tests I've made:

                    Xml test file:

                    <?xml version="1.0" encoding="UTF-8"?>
                    <project>
                    	<version>thisversion</version>
                    </project>
                    

                    First loop (readNext() - no error):

                    while (!xmlReader.atEnd())
                    {
                            QXmlStreamReader::TokenType token = xmlReader.readNext();
                            qDebug() << "readNext():" << token << "- at line:" << xmlReader.lineNumber();
                    }
                    

                    Console output:

                    readNext(): 2 - at line: 1
                    readNext(): 4 - at line: 2
                    readNext(): 6 - at line: 3
                    readNext(): 4 - at line: 3
                    readNext(): 6 - at line: 3
                    readNext(): 5 - at line: 3
                    readNext(): 6 - at line: 4
                    readNext(): 5 - at line: 4
                    readNext(): 3 - at line: 4
                    

                    Second loop (readElementText() - error):

                    while (!xmlReader.atEnd())
                    {
                            xmlReader.readNext();
                            qDebug() << xmlReader.readElementText();
                    }
                    

                    Console output:

                    ""
                    "\n\t"
                    Error: "Expected character data." at line: 3 column: 10 ()
                    
                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #8

                    @Aymeric_Qt said in QXmlStreamReader throws error when reading a sub element:

                    If I only use readNext() it runs fine to the end of the file without any error.

                    It seems to have taken me about six times of asking to extract this vital piece of information from you! I did say right from the start to use only readNext() while you figured out what was the issue, just a standard debugging/development technique.

                    So now you have your answer: go look at the source of readElementText(), say on woboq, and figure what it is doing/why it is raising an error. See https://doc.qt.io/qt-5.15/qxmlstreamreader.html#readElementText for the behaviour parameter you may want to play with to see what is going on.

                    If it's a whitespace issue --- and I don't know whether it is --- you might try with XML:

                    <?xml version="1.0" encoding="UTF-8"?><project><modelVersion>4.0.0</modelVersion></project>
                    

                    to see if that makes any difference.

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      Aymeric_Qt
                      wrote on last edited by
                      #9

                      As expected readElementText() cannot read "complete" (tag and content) child elements.

                      However it is possible to ignore child element or to get only their content by using QXmlStreamReader::ReadElementTextBehaviour enum as parameter.

                      Unfortunately this does not provide a straight forward solution to my problem so I had to found a workaround.

                      For example I want to get all the child elements of the project tag (and ignore all grandchildren):

                      while (!xmlReader.atEnd())
                         {
                             QXmlStreamReader::TokenType token = xmlReader.readNext();
                             qDebug() << "Next token:" << token << xmlReader.tokenString() << "- at line:" << xmlReader.lineNumber() << "- name:" << xmlReader.name();
                             if(token == QXmlStreamReader::StartElement && xmlReader.name() == QString("project"))
                             {
                                 xmlReader.readNext();
                                 while(xmlReader.name() != QString("project"))
                                 {
                                     xmlReader.readNextStartElement();
                                     qDebug() << "- tag:" << xmlReader.name() << "- content:" << xmlReader.readElementText(QXmlStreamReader::SkipChildElements);
                                 }
                             }
                         }
                      

                      Although it's working it is not very elegant and might not be really reusable (e.g. to get the dependencies in a pom.xml file).

                      Thank you for reading.
                      Have a nice day.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved