diff options
Diffstat (limited to 'doc/xml-sax-features-walkthrough.doc')
-rw-r--r-- | doc/xml-sax-features-walkthrough.doc | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/doc/xml-sax-features-walkthrough.doc b/doc/xml-sax-features-walkthrough.doc new file mode 100644 index 000000000..bc57a3c05 --- /dev/null +++ b/doc/xml-sax-features-walkthrough.doc @@ -0,0 +1,391 @@ +/**************************************************************************** +** +** Documentation on the sax interface of the xml module +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the Qt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.QPL +** included in the packaging of this file. Licensees holding valid Qt +** Commercial licenses may use this file in accordance with the Qt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +/*! \page xml-sax-features-walkthrough.html + +\ingroup step-by-step-examples + +\title Walkthrough: Using SAX2 features with the Qt XML classes + +This document assumes that you are familiar with \link xml.html#namespaces +namespaces \endlink in XML and the concept of a \link xml.html#sax2 SAX2 +parser \endlink. +If features of SAX2 readers are new to you please read +\link xml.html#sax2Features the feature section \endlink of the SAX2 document. + +As a novice to the Qt XML classes it is advisable to have a look at the +\link xml-sax-walkthrough.html tiny SAX2 parser walkthrough \endlink before +reading on. + +This walkthrough covers two topics: First of all it shows how to +set SAX2 features and secondly how to integrate the Qt XML functionality +into a Qt GUI application. + +The resulting application allows you to compare the output of the reader +depending on how the two features +\e http://xml.org/sax/features/namespace-prefixes +and \e http://xml.org/sax/features/namespaces are set. +To do this it shows tree views of the read XML file +listing the qualified names of elements and attributes and the respective +namespace URIs. + +<h3>Setting features</h3> + +\quotefile xml/tagreader-with-features/tagreader.cpp + +Let's begin with the main program of the application. First the boring +part: we include all the classes we need: + +\skipto include +\printline structureparser.h +\printuntil qlabel.h + +\link #structureparser.h structureparser.h \endlink contains the API of +the XML parser that we implement in \link #structureparser.cpp +structureparser.cpp. \endlink + +\printline main +\printuntil QApplication + +As usual we then create a Qt application object and hand command line arguments +over to it. + +\printline xmlFile( + +If the user runs the program with one filename as +an argument we process this file, otherwise we use the \e fnord.xml file from +the example directory for demonstration purposes. + +\printline QXmlInputSource + +We use \e xmlFile as the XML Input Source... + +\printline QXmlSimpleReader + +... and instantiate a \e reader object. Later we will manipulate its features +and thus influence how the XML data are read. + +\printline container + +Now let's think about presenting the output: As described in the +\link xml.html#sax2Features Qt SAX2 documentation \endlink +there are three valid combinations of \e +http://xml.org/sax/features/namespace-prefixes +and \e http://xml.org/sax/features/namespaces: TRUE/TRUE, TRUE/FALSE and +FALSE/TRUE. To show the relevant output side by side of each other +and mark them with three labels makes up for a grid layout consisting +of three columns (and thus two lines). + +\printline nameSpace + +The most natural way of presenting XML elements is in a tree. +Thus we use a listview. Its name \e nameSpace indicates that this +one will be used to present the combination of \e +http://xml.org/sax/features/namespaces being TRUE and +\e http://xml.org/sax/features/namespace-prefixes +being FALSE -- the default configuration of a \l QXmlSimpleReader. + +Being the first grid entry the \e nameSpace listview will +appear in the upper left corner of the virtual grid. + +\printline handler + +Then we create a handler that deals with the XML data read by the reader. +As the provided handler class \l QXmlDefaultHandler simply does nothing +with the data from the reader, +we can't use it right away. Instead we have to subclass our +own \link #structureparser.cpp StructureParser \endlink from it. + +\printline setContentHandler + +The \e handler serves as content handler for the reader. Note that +for simplicity reasons we don't register e.g. an error handler. Thus +our program will not complain about for example missing closing tags +in the parsed XML document. + +\printline parse + +Finally we parse the document with the reader's default feature settings. + +\printline namespacePrefix +\printline table_namespace_prefix + +Now we prepare for the parsing of the same XML input source with +different reader settings. The output will be presented in +a second \l QListView, \e namespacePrefix. As it is the second +member of the \e container grid it will appear in the middle of +the upper grid row. + +\printline setListView + +Then we ask the \e handler to present the data in the \e namespacePrefix +listview. + +\printline namespace-prefixes +\printline TRUE + +Now we modify the behaviour of the \e reader and change +\e http://xml.org/sax/features/namespace-prefixes from the default FALSE +to TRUE. The \e http://xml.org/sax/features/namespaces feature has +still its default setting TRUE. + +\printline reset + +We have to reset the input source to make the new parsing start from the +beginning of the document again. + +\printline parse + +Finally we parse the XML file a second time with the changed reader +settings (TRUE/TRUE). + +\printline prefix +\printuntil parse + +Next we prepare and use the upper right listview to show the reader results +with the feature setting \e http://xml.org/sax/features/namespaces +FALSE and \e http://xml.org/sax/features/namespace-prefixes TRUE. + +\printline namespace label +\printuntil namespace prefix label +\printuntil prefix label +\printuntil container + +The second row of the \e container grid is filled with three labels +denoting the reader settings that belong to the above listview. + +\printline app.setMainWidget +\printuntil } + +Same procedure as with every Qt GUI program: the grid serves as the +main widget of our application and is shown. After that we enter +the GUI's event loop. + + +<h3><a name="structureparser.h">The handler API</a></h3> + +Let's have a brief look at the API of our handler class +\e StructureParser: + +\quotefile xml/tagreader-with-features/structureparser.h +\skipto include +\printuntil QString + +\printline StructureParser +\printuntil { + +We derive it from the \l QXmlDefaultHandler class that +implements a handler that simply does nothing. + +\printuntil QListView + +This makes it easy for us to implement only the functionality +we in fact need. In our case this is the constructor that +takes a \l QListView as an argument, + +\printline startElement +\printuntil QXmlAttributes + +the function to execute at the occurrence of element start tags +(inherited from \l QXmlContentHandler), and + +\printline endElement + +the code to run when an end tag occurs. + +All we have to implement so far is content handling. + +\printline setListView + +In addition we have a function that selects a listview +for the output. + +\printuntil QPtrStack + +Keep in mind that we write a SAX2 parser that doesn't +have an object model to keep all elements and attributes +in memory. To display the elements and attributes in a tree like +structure we must however keep track of all elements +that haven't been closed yet. + +To do this we use a LIFO stack +of QListItems. An element will be added to the stack when +its start tag appears and removed +as soon as its end tag is parsed. + +\printline table +\printline }; + +Apart from this we define a member variable that contains +the currently used listview. + +<h3><a name="structureparser.cpp">The handler itself</a></h3> + +Now that we defined the API we have to implement the +relevant functions. + +\quotefile xml/tagreader-with-features/structureparser.cpp +\skipto include +\printuntil qlistview.h + +\printline StructureParser +\printuntil { + +First we have the constructor that takes a listview pointer as +its argument. + +\printline setListView +\printuntil } + +All we have to do here is to prepare the argument \l QListView +before usage. This we do with the \link #setListView() +setListView() \endlink function. + +<a name="setListView()"></a> +\printline setListView +\printuntil table + +First we store the argument away. + +\printline setSorting + +We want the elements to be listed as they appear in the +document -- and not for example sorted alphabetically. That's +why we switch off sorting at all. + +\printline addColumn +\printuntil } + +The listview now consists of two columns: one for the +element's or attribute's qualified names and one for +their namespace URIs. Columns are added from left to right +and with the title as an argument. + +Now let's deal with XML content handling. + +\printline startElement +\printuntil { + +When we come across the start tag of an element the handler does +the real work. Although \e startElement is called with four +arguments we keep track of only three: the namespace URI +of the element, its qualified name and its attributes. +If an element has no namespace assigned or if the feature +settings of the reader don't provide the handler with +namespace URIs at all \e namespaceURI contains an empty +string. + +Note that we don't assign a variable to the second argument -- +we're simply not interested in the local name of the element. + +\printline element + +Whenever an element occurs we want to show it in the listview. +Therefore we define a \l QListViewItem variable. + +\printline stack.isEmpty() +\printline stack.top() + +As long as the element \e stack isn't empty the current element +is a child of the topmost (last unclosed) element on the stack. Thus we +create a new \l QListViewItem as a child of QPtrStack::stack.top() with +the new element's qualified name in the first column and the according +namespace URI (or nothing) in the second one. + +The QListViewItem is usally inserted as the first child. This means that we +would get the elements in reverse order. So we first search for the last +child of the QPtrStack::stack.top() element and insert it after this +element. + +In a valid XML document this applies to all elements except +the document root. + +\printuntil table +\printline } + +The root element we have to handle separately because it is +the first element to go onto the \l QListViewItem stack. +Its listview item is therefore a direct child of the +\e table listview itself. + +\printline stack.push + +Now we put the element's listview item on top of the stack. + +\printline setOpen + +By default a QListView presents all of its nodes closed. +The user may then click on the \e + icon to see the child +entries. + +We however want to see the entire element tree +at once when we run the program. +Therefore we open each listview item manually. + +\printline attributes.length + +What do we do if an element has attributes? + +\printuntil } +\printline } + +For each of them we create a new listview item to present the attribute's +qualified name and the relevant namespace URI (or nothing). +Obviously \e attribute is a child of +the current \e element. + + +\printline TRUE +\printline } + +To prevent the reader from throwing an error we have to +return TRUE when we successfully dealt with an +element's start tag. + +\printline endElement +\printuntil stack.pop + +Whenever we come across an element's closing tag we +have to remove its listview item from the stack as +it can't have children any longer. + +\printuntil } + +And so we're done. + +*/ |