XmlDataAccess

Since: BlackBerry 10.0.0

#include <bb/data/XmlDataAccess>

To link against this class, add the following line to your .pro file: LIBS += -lbbdata

Converts data from XML format to Qt C++ value objects or from Qt C++ value objects to XML format.

Load operations read and parse XML (Extensible Markup Language) data coming from a file or memory buffer into a tree of Qt value objects. Save operations convert Qt value objects into XML format which are written to a file or returned in a memory buffer.

NOTE: Save-to-XML has serious limitations described at the end of this documentation in "Saving Qt data as XML".

Both XML and Qt support unlimited nesting of hierarchical data.

XML terminology

Markup and Content

The characters which make up an XML document are divided into markup and content. All strings which constitute markup either begin with the character < and end with a >, or begin with the character & and end with a ;. Strings of characters which are not markup are content.

Tag

A tag is a markup construct that begins with < and ends with >. Tags come in three flavors:
  • start-tags: for example, <section>

  • end-tags: for example, </section>

  • empty-element tags: for example, <line-break />

Element

An element is a logical document component either begins with a start-tag and ends with a matching end-tag or consists only of an empty-element tag. The characters between the start- and end-tags, if any, are the element's content, and may contain markup, including other elements, which are called child elements. An example of an element is <Greeting>Hello, world.</Greeting> (see hello world). Another example is <line-break />.

Attribute

An attribute is a markup construct consisting of a name/value pair that exists within a start-tag or an empty-element tag. In the example below the element img has two attributes, src and alt:

<img src="madonna.jpg" alt='Foligno Madonna, by Raphael' />.

Loading XML Data in Qt

The XML data generally consists of name-value pairs stored in a hierarchy. In all cases, except for the root element, the name will be used as the key for an entry in the parent's map. So, XML name-value data is stored like this in Qt:

parentMap["name"] = value

The XML value data is mapped to Qt values as follows:

   XML Type                          Qt Value
   ---------                         -----------------
   parent element (*)                QVariant(QVariantMap)
   repeating element                 QVariant(QVariantList)
   element with no children          QVariant(QString)
   attribute                         QVariant(QString)

The (*) element is considered a parent if it has any attributes or child elements. Also, QVariantMap is defined as a QMap<QString, QVariant> and QVariantList is defined as a QList<QVariant>.

Two special map entries:

  1. For the root element a special entry is added to the top-level Qt map to record the root element name:
    topMap[".root"] = "<root-element-name>"
    
  2. A parent element which has character data will have that data stored as a special entry in the parent map:
    parentMap[".data"] = "<character-data>"
    

Here is an example to make the translation from XML to Qt clearer:

contacts.xml

<contacts version="1.0">
    <contact>
        <id>1</id>
        <title>Sr. Editor</title>
        <firstname>Mike</firstname>
        <lastname>Chepesky</lastname>
    </contact>
    <contact>
        <id>2</id>
        <title>Talent Scout</title>
        <firstname>Westlee</firstname>
        <lastname>Barichak</lastname>
        <phonenumber>+465256467</phonenumber>
        <phonenumber>+464746734</phonenumber>
        some additional character data
    </contact>
    ...
</contacts>

Qt data structure for contacts:

A. QVariant(QVariantMap) contains:
   map[".root"]       = QVariant("contacts")
   map["version"]     = QVariant("1.0")
   map["contact"]     = QVariant(QVariantList)[see B]
B. QVariant(QVariantList) contains:
   [0] = QVariant(QVariantMap)                [see C]
   [1] = QVariant(QVariantMap)                [see D]
   [2] ...
C. QVariant(QVariantMap) contains:
   map["id"]          = QVariant("1")
   map["firstname"]   = QVariant("Mike")
   map["lastname"]    = QVariant("Chepesky")
   map["title"]       = QVariant("Sr. Editor")
D. QVariant(QVariantMap) contains:
   map[".data"]       = QVariant("some additional character data")
   map["id"]          = QVariant("2")
   map["firstname"]   = QVariant("Westlee")
   map["lastname"]    = QVariant("Barichak")
   map["title"]       = QVariant("Talent Scout")
   map["phonenumber"] = QVariant(QVariantList)[see E]
E. QVariant(QVariantList) contains:
   [0] = QVariant("+465256467")
   [1] = QVariant("+464746734")

Loading data in C++

Here's an example that shows how to load data in C++:

// Create a data model with sorting keys for lastname and firstname
GroupDataModel *model =
  new GroupDataModel(QStringList() << "lastname" << "firstname");

// Load the XML data from local file
XmlDataAccess xda;
QVariant list = xda.load("contacts.xml", "/contacts/contact");

// Add the data to the model
model->insertList(list.value<QVariantList>());

// Create a ListView control and add the model to the list
ListView *listView = new ListView();
listView->setDataModel(model);

Loading data in QML

Here's an example that shows how to load data in QML (note that DataSource is used for data loading from QML and that XmlDataAccess is being used internally by DataSource to perform the XML parsing here):

import bb.cascades 1.0
import bb.data 1.0
Page {
  content: ListView {
    id: listView
    dataModel: dataModel
    //...
  }
  attachedObjects: [
    GroupDataModel {
      id: dataModel
    },
    DataSource {
      id: dataSource
      source: "contacts.xml"
      query: "/contacts/contact"
      onDataLoaded: {
        if (data[0] == undefined) {
          // The data returned is not a list, just one QVariantMap.
          // Use insert to add one element.
          dataModel.insert(data)
        } else {
          //The data returned is a list. Use insertList.
          dataModel.insertList(data)
        }
      }
    }
  ]
  onCreationCompleted: { dataSource.load(); }
}

Saving Qt data as XML

Note that the save-to-XML support in this version has some serious limitations since the XML output is well-formed (based on the rules of XML markup) but it is not necessarily valid since it does not conform to any schema definition. In particular the choice of whether to output character data as an attribute (name="value") or as an element (<name>value</name>) is not under the developer's control and is based on some simple but arbitrary rules.

Other limitations due to there being no schema include:
  • No data type constraints (number, date, etc.) for character data.

  • The order of elements and attributes will not be preserved.
    • The order will be alphabetical, not the original xml order.

    • The order of repeating elements (contacts in example above) will be preserved.

This makes the saving of data in XML format suitable for use as temporary private storage of structured data. It will NOT be suitable for communicating with an external system which expects valid XML based on a published schema.

Attribute versus element rules

The {name, value} data is output as an XML attribute (name="value") if:
  • The parent XML node already has character data

  • OR the name is an XML namespace declaration like "xmlns:atom"

Otherwise, the data is output as an XML element (<name>value</name>). As an example of the first point, the data will be written as:

<aaa name="value">more character data</aaa>
Rather than written as:
<aaa>
    more character data
    <name>value</name>
</aaa>


Overview

Public Functions Index

XmlDataAccess (QObject *parent=0)
virtual ~XmlDataAccess ()
DataAccessErrorerror () const
boolhasError () const
QVariantload (const QString &filePath, const QString &queryPath="")
QVariantload (QIODevice *ioDevice, const QString &queryPath="")
QVariantloadFromBuffer (const QByteArray &buffer, const QString &queryPath="")
QVariantloadFromBuffer (const QString &buffer, const QString &queryPath="")
voidsave (const QVariant &data, const QString &filePath)
voidsave (const QVariant &data, QIODevice *ioDevice)
voidsaveToBuffer (const QVariant &data, QByteArray *buffer)
voidsaveToBuffer (const QVariant &data, QString *buffer)

Public Functions

XmlDataAccess (

Constructs a XmlDataAccess object with a parent.

Parameters
parent

The parent owner or 0. Optional and will default to 0 if not specified.

Since:

BlackBerry 10.0.0

virtual~XmlDataAccess ()

Destructor.

Since:

BlackBerry 10.0.0

DataAccessError error ()

Returns an error object for the most recent operation.

Return:

DataAccessError with error type and error message.

Since:

BlackBerry 10.0.0

bool hasError ()

Returns indication of whether or not most recent operation ended with an error.

Return:

true if current error or false if none.

Since:

BlackBerry 10.0.0

QVariant load (

Load the XML data from file and return it as a hierarchy of Qt value objects.

The queryPath only supports simple hierarchical paths and not XPATH expressions.

The returned data is either a QVariantList or a QVariantMap cast as a QVariant.

You can use DataAccess::hasError() to determine if the most recent operation resulted in an error, and you can use DataAccess::error() to retrieve information about the error that occurred.

Parameters
filePath

The path to the XML file.

queryPath

Optional path to node for the subset of xml to return [defaults to root node].

Return:

A QVariant containing a hierarchy of Qt value objects.

Since:

BlackBerry 10.0.0

QVariant load (

Load the XML data from I/O device and return it as a hierarchy of Qt value objects.

The queryPath only supports simple hierarchical paths and not XPATH expressions.

The returned data is either a QVariantList or a QVariantMap cast as a QVariant.

You can use DataAccess::hasError() to determine if the most recent operation resulted in an error, and you can use DataAccess::error() to retrieve information about the error that occurred.

Parameters
ioDevice

Used to read or write data. QIODevice can represent a number of useful types including QBuffer and QFile.

queryPath

Optional path to node for the subset of xml to return [defaults to root node].

Return:

A QVariant containing a hierarchy of Qt value objects.

Since:

BlackBerry 10.0.0

QVariant loadFromBuffer (

Parse the XML byte array buffer and return it as a hierarchy of Qt value objects.

The queryPath only supports simple hierarchical paths and not XPATH expressions.

The returned data is either a QVariantList or a QVariantMap cast as a QVariant.

You can use DataAccess::hasError() to determine if the most recent operation resulted in an error, and you can use DataAccess::error() to retrieve information about the error that occurred.

Parameters
buffer

An in-memory byte array containing XML data.

queryPath

Optional path to node for the subset of xml to return [defaults to root node].

Return:

A QVariant containing a hierarchy of Qt value objects.

Since:

BlackBerry 10.0.0

QVariant loadFromBuffer (

Parse the XML string buffer and return it as a hierarchy of Qt value objects.

The queryPath only supports simple hierarchical paths and not XPATH expressions.

The returned data is either a QVariantList or a QVariantMap cast as a QVariant.

You can use DataAccess::hasError() to determine if the most recent operation resulted in an error, and you can use DataAccess::error() to retrieve information about the error that occurred.

Parameters
buffer

An in-memory string containing XML data.

queryPath

Optional path to node for the subset of xml to return [defaults to root node].

Return:

A QVariant containing a hierarchy of Qt value objects.

Since:

BlackBerry 10.0.0

void save (

Save the XML data to the file.

The data parameter is a QVariant. See table of types in this class. Unless the data is a single primitive value it should be either a QVariantList (representing an XML array) or a QVariantMap (representing an XML object) cast as a QVariant.

You can use DataAccess::hasError() to determine if the most recent operation resulted in an error, and you can use DataAccess::error() to retrieve information about the error that occurred.

Parameters
data

to be converted to XML format and saved to file.

filePath

The path to the XML file.

Since:

BlackBerry 10.0.0

void save (

Save the XML data to the I/O device.

The data parameter is a QVariant. See table of types in this class. Unless the data is a single primitive value it should be either a QVariantList (representing an XML array) or a QVariantMap (representing an XML object) cast as a QVariant.

You can use DataAccess::hasError() to determine if the most recent operation resulted in an error, and you can use DataAccess::error() to retrieve information about the error that occurred.

Parameters
data

to be converted to XML format and saved to file.

ioDevice

Used to read or write data. QIODevice can represent a number of useful types including QBuffer and QFile.

Since:

BlackBerry 10.0.0

void saveToBuffer (

Save the XML data to the buffer parameter.

The data parameter is a QVariant. See table of types in this class. Unless the data is a single primitive value it should be either a QVariantList (representing an XML array) or a QVariantMap (representing an XML object) cast as a QVariant.

You can use DataAccess::hasError() to determine if the most recent operation resulted in an error, and you can use DataAccess::error() to retrieve information about the error that occurred.

Parameters
data

to be converted to XML format and saved to buffer.

buffer

output parameter which is updated with XML-formatted data.

Since:

BlackBerry 10.0.0

void saveToBuffer (

Save the XML data to the buffer parameter.

The data parameter is a QVariant. See table of types in this class. Unless the data is a single primitive value it should be either a QVariantList (representing an XML array) or a QVariantMap (representing an XML object) cast as a QVariant.

You can use DataAccess::hasError() to determine if the most recent operation resulted in an error, and you can use DataAccess::error() to retrieve information about the error that occurred.

Parameters
data

to be converted to XML format and saved to buffer.

buffer

output parameter which is updated with XML-formatted data.

Since:

BlackBerry 10.0.0

Last modified: 2014-06-24



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus