Add documentation for parsing XML with Qt

This commit is contained in:
Florian Weimer 2013-04-24 12:09:44 +02:00
parent 08d55e3b9b
commit 38f436ea1c
7 changed files with 262 additions and 0 deletions

View file

@ -255,6 +255,62 @@
</para>
</section>
<section id="sect-Defensive_Coding-Tasks-Serialization-Qt">
<title>Using Qt for XML parsing</title>
<para>
The XML component of Qt, QtXml, does not resolve external IDs
by default, so it is not requred to prevent such resolution.
Internal entities are processed, though. To change that, a
custom <literal>QXmlDeclHandler</literal> and
<literal>QXmlSimpleReader</literal> subclasses are needed. It
is not possible to use the
<function>QDomDocument::setContent(const QByteArray
&amp;)</function> convenience methods.
</para>
<para>
<xref linkend="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-NoEntityHandler"/>
shows an entity handler which always returns errors, causing
parsing to stop when encountering entity declarations.
</para>
<example id="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-NoEntityHandler">
<title>A QtXml entity handler which blocks entity processing</title>
<xi:include href="snippets/Serialization-XML-Qt-NoEntityHandler.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</example>
<para>
This handler is used in the custom
<literal>QXmlReader</literal> subclass in <xref
linkend="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-NoEntityReader"/>.
Some parts of QtXml will call the
<function>setDeclHandler(QXmlDeclHandler *)</function> method.
Consequently, we prevent overriding our custom handler by
providing a definition of this method which does nothing. In
the constructor, we activate namespace processing; this part
may need adjusting.
</para>
<example id="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-NoEntityReader">
<title>A QtXml XML reader which blocks entity processing</title>
<xi:include href="snippets/Serialization-XML-Qt-NoEntityReader.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</example>
<para>
Our <literal>NoEntityReader</literal> class can be used with
one of the overloaded
<function>QDomDocument::setContent</function> methods.
<xref linkend="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-QDomDocument"/>
shows how the <literal>buffer</literal> object (of type
<literal>QByteArray</literal>) is wrapped as a
<literal>QXmlInputSource</literal>. After calling the
<function>setContent</function> method, you should check the
return value and report any error.
</para>
<example id="ex-Defensive_Coding-Tasks-Serialization-XML-Qt-QDomDocument">
<title>Parsing an XML document with QDomDocument, without entity expansion</title>
<xi:include href="snippets/Serialization-XML-Qt-QDomDocument.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</example>
</section>
<section id="sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse">
<title>Using OpenJDK for XML parsing and validation</title>
<para>

View file

@ -0,0 +1,42 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<!-- Automatically generated file. Do not edit. -->
<programlisting language="C">
class NoEntityHandler : public QXmlDeclHandler {
public:
bool attributeDecl(const QString&#38;, const QString&#38;, const QString&#38;,
const QString&#38;, const QString&#38;);
bool internalEntityDecl(const QString&#38;, const QString&#38;);
bool externalEntityDecl(const QString&#38;, const QString&#38;,
const QString&#38;);
QString errorString() const;
};
bool
NoEntityHandler::attributeDecl
(const QString&#38;, const QString&#38;, const QString&#38;, const QString&#38;,
const QString&#38;)
{
return false;
}
bool
NoEntityHandler::internalEntityDecl(const QString&#38;, const QString&#38;)
{
return false;
}
bool
NoEntityHandler::externalEntityDecl(const QString&#38;, const QString&#38;, const
QString&#38;)
{
return false;
}
QString
NoEntityHandler::errorString() const
{
return "XML declaration not permitted";
}
</programlisting>

View file

@ -0,0 +1,25 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<!-- Automatically generated file. Do not edit. -->
<programlisting language="C">
class NoEntityReader : public QXmlSimpleReader {
NoEntityHandler handler;
public:
NoEntityReader();
void setDeclHandler(QXmlDeclHandler *);
};
NoEntityReader::NoEntityReader()
{
QXmlSimpleReader::setDeclHandler(&#38;handler);
setFeature("http://xml.org/sax/features/namespaces", true);
setFeature("http://xml.org/sax/features/namespace-prefixes", false);
}
void
NoEntityReader::setDeclHandler(QXmlDeclHandler *)
{
// Ignore the handler which was passed in.
}
</programlisting>

View file

@ -0,0 +1,16 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<!-- Automatically generated file. Do not edit. -->
<programlisting language="C">
NoEntityReader reader;
QBuffer buffer(&#38;data);
buffer.open(QIODevice::ReadOnly);
QXmlInputSource source(&#38;buffer);
QDomDocument doc;
QString errorMsg;
int errorLine;
int errorColumn;
bool okay = doc.setContent
(&#38;source, &#38;reader, &#38;errorMsg, &#38;errorLine, &#38;errorColumn);
</programlisting>

View file

@ -3,5 +3,6 @@
/TLS-Client-NSS
/TLS-Client-OpenSSL
/XML-Parser-Expat
/XML-Parser-Qt
*.class
*.o

View file

@ -0,0 +1,120 @@
#include <QtCore/QBuffer>
#include <QtCore/QByteArray>
#include <QtCore/QFile>
#include <QtXml/QDomDocument>
#include <QtXml/QXmlSimpleReader>
#include <stdio.h>
namespace {
//+ Tasks Serialization-XML-Qt-NoEntityHandler
class NoEntityHandler : public QXmlDeclHandler {
public:
bool attributeDecl(const QString&, const QString&, const QString&,
const QString&, const QString&);
bool internalEntityDecl(const QString&, const QString&);
bool externalEntityDecl(const QString&, const QString&,
const QString&);
QString errorString() const;
};
bool
NoEntityHandler::attributeDecl
(const QString&, const QString&, const QString&, const QString&,
const QString&)
{
return false;
}
bool
NoEntityHandler::internalEntityDecl(const QString&, const QString&)
{
return false;
}
bool
NoEntityHandler::externalEntityDecl(const QString&, const QString&, const
QString&)
{
return false;
}
QString
NoEntityHandler::errorString() const
{
return "XML declaration not permitted";
}
//-
//+ Tasks Serialization-XML-Qt-NoEntityReader
class NoEntityReader : public QXmlSimpleReader {
NoEntityHandler handler;
public:
NoEntityReader();
void setDeclHandler(QXmlDeclHandler *);
};
NoEntityReader::NoEntityReader()
{
QXmlSimpleReader::setDeclHandler(&handler);
setFeature("http://xml.org/sax/features/namespaces", true);
setFeature("http://xml.org/sax/features/namespace-prefixes", false);
}
void
NoEntityReader::setDeclHandler(QXmlDeclHandler *)
{
// Ignore the handler which was passed in.
}
//-
}
int
main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: %s XML-FILE\n", argv[0]);
return 1;
}
QByteArray data;
{
QFile f(argv[1]);
if (!f.open(QIODevice::ReadOnly)) {
fprintf(stderr, "error: could not open file: %s\n", argv[1]);
return 1;
}
data = f.readAll();
if (f.error()) {
fprintf(stderr, "error: could not read file: %s\n", argv[1]);
return 1;
}
}
//+ Tasks Serialization-XML-Qt-QDomDocument
NoEntityReader reader;
QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly);
QXmlInputSource source(&buffer);
QDomDocument doc;
QString errorMsg;
int errorLine;
int errorColumn;
bool okay = doc.setContent
(&source, &reader, &errorMsg, &errorLine, &errorColumn);
//-
if (!okay) {
fprintf(stderr, "%d:%d: %s\n", errorLine, errorColumn,
errorMsg.toUtf8().constData());
return 1;
}
data = doc.toByteArray(1);
if (fwrite(data.constData(), data.size(), 1, stdout) != 1) {
perror("fwrite");
return 1;
}
return 0;
}

View file

@ -28,6 +28,8 @@ CFLAGS_TLS-Client-NSS = -I/usr/include/nspr4 -I/usr/include/nss3
LIBS_TLS-Client-NSS = -lnss3 -lnspr4 -lssl3
compile_and_link += XML-Parser-Expat
LIBS_XML-Parser-Expat = -lexpat
compile_and_link += XML-Parser-Qt
LIBS_XML-Parser-Qt = -lQtCore -lQtXml
# Define preprocessor symbols if certain functions exist.
CHECK_FUNCTION = crypto/X509_check_host/-DHAVE_X509_CHECK_HOST \