Search code examples
qtxqueryqtxml

Not able to parse this QString(in XML format) using XQuery


I want to parse the following xml (get the type ids and the test output and so on)stored in the QString expected_xml using XQuery,

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE TEST_XML>
<TEST TEST_VERSION="14">
 <TEST_TYPES>
  <TEST_TYPE ID="0"/>
  <TEST_TYPE ID="1"/>
 </TEST_TYPES>
 <TEST_QUERY_LIST PROP="0">
  <TEST_QUERY_FILE>"C:/Files/File.txt"</TEST_QUERY_FILE>
 </TEST_QUERY_LIST>
 <TEST_OUTPUT>
  <FILE PATH="C:/Files/File2.txt" TEST_TYPE_ID_REF="1">
   <USED_BY TEST_PATH="C:/Files/File2.txt" ALIAS="thisData"/>
  </FILE>
 </TEST_OUTPUT>
</TEST>

I use the following code to get the Ids for example, but this does not give me nothing. Do I miss anything very obvious ?

   //Test Parsing
   QByteArray xmlByteArry;
   QBuffer device(&xmlByteArry);
   device.setData(expected_xml.toUtf8());
   device.open(QIODevice::ReadOnly);

   QXmlQuery query;
   query.bindVariable("xmlByteArry", &device);
   query.setQuery("doc($xmlByteArry)//TEST/TEST_TYPES");

   if(query.isValid())
   {
      QStringList values;
      query.evaluateTo(&values);
      qDebug() << values;
   }

Solution

  • If you need the Id's, your Query is wrong. It should be:

        query.setQuery("doc($xmlByteArry)//TEST/TEST_TYPES/TEST_TYPE/@ID");
    

    This Query returns the value of the Attributes.

    Additional Info: If you have Errors in your Xml Query you can set a MessageHandler to read the Errors:

    class MessageHandler: public QAbstractMessageHandler
    {
        virtual void handleMessage(QtMsgType type,
            const QString &description,
            const QUrl &identifier,
            const QSourceLocation &sourceLocation)
        {
            qDebug() << QString("Xml Query Error: %1 at Line: %2 Character:")
                .arg(description).arg(sourceLocation.line()).arg(sourceLocation.column());
        }
    };
    

    Here is a small Example that reads the Attribute ID to a StringList:

    bool test7::test()
    {
        QByteArray xmlByteArry;
        QBuffer device(&xmlByteArry);
        device.setData(XmlTree().toUtf8());
        device.open(QIODevice::ReadOnly);
    
        QXmlQuery query;
        query.setMessageHandler(new MessageHandler());
        query.bindVariable("xmlByteArry", &device);
        query.setQuery("doc($xmlByteArry)//TEST/TEST_TYPES/TEST_TYPE/@ID");
    
        QStringList values;
        if(query.isValid())
        {
            QXmlResultItems result;
            query.evaluateTo(&result);
    
            QXmlItem XmlItem(result.next());
    
            while (!XmlItem.isNull()) 
            {
                if (XmlItem.isNode()) 
                {
                    QXmlNodeModelIndex Index = XmlItem.toNodeModelIndex();
                    values.append(Index.stringValue());
                }
    
                XmlItem = result.next();
            }
        }
    
        return true;
    }
    

    For more Information read the Qt XQuery Documentation: here

    UPDATE: You can get the TESTPATH and PATH for a ID with the following query:

    query.setQuery("for $x in doc($xmlByteArry)//TEST/TEST_OUTPUT/FILE"
            " return if($x/@TEST_TYPE_ID_REF = 1) "
            " then ($x/USED_BY/@TEST_PATH, $x/@PATH ) "
            " else ()");
    

    Set the ID Value programmatically.