Add documentation for parsing XML with Qt
This commit is contained in:
parent
08d55e3b9b
commit
38f436ea1c
7 changed files with 262 additions and 0 deletions
|
@ -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
|
||||
&)</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>
|
||||
|
|
|
@ -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&, 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";
|
||||
}
|
||||
</programlisting>
|
|
@ -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(&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>
|
|
@ -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(&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);
|
||||
</programlisting>
|
1
defensive-coding/src/.gitignore
vendored
1
defensive-coding/src/.gitignore
vendored
|
@ -3,5 +3,6 @@
|
|||
/TLS-Client-NSS
|
||||
/TLS-Client-OpenSSL
|
||||
/XML-Parser-Expat
|
||||
/XML-Parser-Qt
|
||||
*.class
|
||||
*.o
|
||||
|
|
120
defensive-coding/src/XML-Parser-Qt.cpp
Normal file
120
defensive-coding/src/XML-Parser-Qt.cpp
Normal 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;
|
||||
}
|
|
@ -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 \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue