Add support for DOCTYPE to wxXmlDocument.
Allow retrieving the DOCTYPE specified in an existing document as well as specifying the DOCTYPE to use when writing a new one. Closes #13779.
This commit is contained in:
committed by
Vadim Zeitlin
parent
41b1ed9c2e
commit
d13278ecc3
@@ -47,6 +47,7 @@ All:
|
|||||||
|
|
||||||
- Allow calling wxItemContainer::Add() and similar with std::vector<> argument.
|
- Allow calling wxItemContainer::Add() and similar with std::vector<> argument.
|
||||||
- Add "%z" support to printf()-like functions like wxString::Format() (RIVDSL).
|
- Add "%z" support to printf()-like functions like wxString::Format() (RIVDSL).
|
||||||
|
- Add DOCTYPE support to wxXmlDocument (Nick Matthews).
|
||||||
- Add wxPowerResourceBlocker (Tobias Taschner).
|
- Add wxPowerResourceBlocker (Tobias Taschner).
|
||||||
- Add wxApp::StoreCurrentException() and RethrowStoredException() and implement
|
- Add wxApp::StoreCurrentException() and RethrowStoredException() and implement
|
||||||
their functionality by default when using C++11 compiler.
|
their functionality by default when using C++11 compiler.
|
||||||
|
@@ -236,6 +236,35 @@ inline void wxXmlNode::SetProperties(wxXmlAttribute *prop)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class WXDLLIMPEXP_XML wxXmlDoctype
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit
|
||||||
|
wxXmlDoctype(const wxString& name = wxString(),
|
||||||
|
const wxString& sysid = wxString(),
|
||||||
|
const wxString& pubid = wxString())
|
||||||
|
: m_rootName(name), m_systemId(sysid), m_publicId(pubid)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Default copy ctor and assignment operators are ok.
|
||||||
|
|
||||||
|
bool IsValid() const;
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
const wxString& GetRootName() const { return m_rootName; }
|
||||||
|
const wxString& GetSystemId() const { return m_systemId; }
|
||||||
|
const wxString& GetPublicId() const { return m_publicId; }
|
||||||
|
|
||||||
|
wxString GetFullString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxString m_rootName;
|
||||||
|
wxString m_systemId;
|
||||||
|
wxString m_publicId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// special indentation value for wxXmlDocument::Save
|
// special indentation value for wxXmlDocument::Save
|
||||||
#define wxXML_NO_INDENTATION (-1)
|
#define wxXML_NO_INDENTATION (-1)
|
||||||
|
|
||||||
@@ -287,6 +316,7 @@ public:
|
|||||||
// Note: this is the encoding original file was saved in, *not* the
|
// Note: this is the encoding original file was saved in, *not* the
|
||||||
// encoding of in-memory representation!
|
// encoding of in-memory representation!
|
||||||
const wxString& GetFileEncoding() const { return m_fileEncoding; }
|
const wxString& GetFileEncoding() const { return m_fileEncoding; }
|
||||||
|
const wxXmlDoctype& GetDoctype() const { return m_doctype; }
|
||||||
|
|
||||||
// Write-access methods:
|
// Write-access methods:
|
||||||
wxXmlNode *DetachDocumentNode() { wxXmlNode *old=m_docNode; m_docNode=NULL; return old; }
|
wxXmlNode *DetachDocumentNode() { wxXmlNode *old=m_docNode; m_docNode=NULL; return old; }
|
||||||
@@ -295,6 +325,7 @@ public:
|
|||||||
void SetRoot(wxXmlNode *node);
|
void SetRoot(wxXmlNode *node);
|
||||||
void SetVersion(const wxString& version) { m_version = version; }
|
void SetVersion(const wxString& version) { m_version = version; }
|
||||||
void SetFileEncoding(const wxString& encoding) { m_fileEncoding = encoding; }
|
void SetFileEncoding(const wxString& encoding) { m_fileEncoding = encoding; }
|
||||||
|
void SetDoctype(const wxXmlDoctype& doctype) { m_doctype = doctype; }
|
||||||
void AppendToProlog(wxXmlNode *node);
|
void AppendToProlog(wxXmlNode *node);
|
||||||
|
|
||||||
#if !wxUSE_UNICODE
|
#if !wxUSE_UNICODE
|
||||||
@@ -313,6 +344,7 @@ private:
|
|||||||
#if !wxUSE_UNICODE
|
#if !wxUSE_UNICODE
|
||||||
wxString m_encoding;
|
wxString m_encoding;
|
||||||
#endif
|
#endif
|
||||||
|
wxXmlDoctype m_doctype;
|
||||||
wxXmlNode *m_docNode;
|
wxXmlNode *m_docNode;
|
||||||
|
|
||||||
void DoCopy(const wxXmlDocument& doc);
|
void DoCopy(const wxXmlDocument& doc);
|
||||||
|
@@ -44,13 +44,16 @@ enum wxXmlNodeType
|
|||||||
of pseudo-attributes these do not use the nodes attribute system. It is the users
|
of pseudo-attributes these do not use the nodes attribute system. It is the users
|
||||||
responsibility to code and decode the instruction text.
|
responsibility to code and decode the instruction text.
|
||||||
|
|
||||||
|
The @c wxXML_DOCUMENT_TYPE_NODE is not implemented at this time. Instead,
|
||||||
|
get and set the DOCTYPE values using the wxXmlDocument class.
|
||||||
|
|
||||||
If @c wxUSE_UNICODE is 0, all strings are encoded in the encoding given to
|
If @c wxUSE_UNICODE is 0, all strings are encoded in the encoding given to
|
||||||
wxXmlDocument::Load (default is UTF-8).
|
wxXmlDocument::Load (default is UTF-8).
|
||||||
|
|
||||||
@library{wxxml}
|
@library{wxxml}
|
||||||
@category{xml}
|
@category{xml}
|
||||||
|
|
||||||
@see wxXmlDocument, wxXmlAttribute
|
@see wxXmlDocument, wxXmlDoctype, wxXmlAttribute
|
||||||
*/
|
*/
|
||||||
class wxXmlNode
|
class wxXmlNode
|
||||||
{
|
{
|
||||||
@@ -433,6 +436,99 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@class wxXmlDoctype
|
||||||
|
|
||||||
|
Represents a DOCTYPE Declaration.
|
||||||
|
|
||||||
|
Example DOCTYPE: <tt>\<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"\></tt>.
|
||||||
|
|
||||||
|
In the above example, "plist" is the name of root element,
|
||||||
|
"-//Apple//DTD PLIST 1.0//EN" (without the quotes) is the public identifier and
|
||||||
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd" (again, without the quotes) is
|
||||||
|
the system identifier.
|
||||||
|
|
||||||
|
A valid DOCTYPE exists in one of following forms:
|
||||||
|
|
||||||
|
1. A root element name.
|
||||||
|
2. A root element name and a system identifier.
|
||||||
|
3. A root element name, a system identifier and a public identifier.
|
||||||
|
4. A root element name and a public identifier. Although this form is not
|
||||||
|
valid XML it is valid for SMGL.
|
||||||
|
|
||||||
|
The DOCTYPE may also contain an internal subset of declarations
|
||||||
|
added between square brackets at the end.
|
||||||
|
These have not been implemented at this time.
|
||||||
|
|
||||||
|
@since 3.1.0
|
||||||
|
|
||||||
|
@library{wxxml}
|
||||||
|
@category{xml}
|
||||||
|
|
||||||
|
@see wxXmlDocument
|
||||||
|
*/
|
||||||
|
class wxXmlDoctype
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Creates and possible initializes the DOCTYPE.
|
||||||
|
|
||||||
|
@param name
|
||||||
|
The root name.
|
||||||
|
@param sysid
|
||||||
|
The system identifier.
|
||||||
|
@param pubid
|
||||||
|
The public identifier.
|
||||||
|
*/
|
||||||
|
wxXmlDoctype(const wxString& rootName = wxString(),
|
||||||
|
const wxString& systemId = wxString(),
|
||||||
|
const wxString& publicId = wxString());
|
||||||
|
|
||||||
|
/**
|
||||||
|
Removes all the DOCTYPE values.
|
||||||
|
*/
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the root name of the document.
|
||||||
|
*/
|
||||||
|
const wxString& GetRootName() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the system id of the document.
|
||||||
|
*/
|
||||||
|
const wxString& GetSystemId() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the public id of the document.
|
||||||
|
*/
|
||||||
|
const wxString& GetPublicId() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the formatted DOCTYPE contents.
|
||||||
|
|
||||||
|
This consists of all the text shown between the opening
|
||||||
|
"<!DOCTYPE " and closing ">" of a DOCTYPE declaration.
|
||||||
|
|
||||||
|
If this object is empty or invalid, i.e. IsValid() returns false, this
|
||||||
|
method returns an empty string.
|
||||||
|
*/
|
||||||
|
wxString GetFullString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns true if the contents can produce a valid DOCTYPE string.
|
||||||
|
|
||||||
|
For an object to be valid, it must have a non-empty root name and a
|
||||||
|
valid system identifier (currently the validity checks of the latter
|
||||||
|
are limited to checking that it doesn't contain both single and double
|
||||||
|
quotes).
|
||||||
|
*/
|
||||||
|
bool IsValid() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//* special indentation value for wxXmlDocument::Save
|
//* special indentation value for wxXmlDocument::Save
|
||||||
#define wxXML_NO_INDENTATION (-1)
|
#define wxXML_NO_INDENTATION (-1)
|
||||||
|
|
||||||
@@ -526,10 +622,14 @@ enum wxXmlDocumentLoadFlag
|
|||||||
doc.Save("myfile2.xml"); // myfile2.xml != myfile.xml
|
doc.Save("myfile2.xml"); // myfile2.xml != myfile.xml
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
|
If the root name value of the DOCTYPE is set, either by loading a file with a
|
||||||
|
DOCTYPE declaration or by setting it directly with the SetDoctype member,
|
||||||
|
then a DOCTYPE declaration will be added immediately after the XML declaration.
|
||||||
|
|
||||||
@library{wxxml}
|
@library{wxxml}
|
||||||
@category{xml}
|
@category{xml}
|
||||||
|
|
||||||
@see wxXmlNode, wxXmlAttribute
|
@see wxXmlNode, wxXmlAttribute, wxXmlDoctype
|
||||||
*/
|
*/
|
||||||
class wxXmlDocument : public wxObject
|
class wxXmlDocument : public wxObject
|
||||||
{
|
{
|
||||||
@@ -612,6 +712,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
const wxString& GetFileEncoding() const;
|
const wxString& GetFileEncoding() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the DOCTYPE declaration data for the document.
|
||||||
|
|
||||||
|
@since 3.1.0
|
||||||
|
*/
|
||||||
|
const wxXmlDoctype& GetDoctype() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the document node of the document.
|
Returns the document node of the document.
|
||||||
|
|
||||||
@@ -700,6 +807,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SetFileEncoding(const wxString& encoding);
|
void SetFileEncoding(const wxString& encoding);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the data which will appear in the DOCTYPE declaration when the
|
||||||
|
document is saved.
|
||||||
|
|
||||||
|
@since 3.1.0
|
||||||
|
*/
|
||||||
|
void SetDoctype(const wxXmlDoctype& doctype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the root element node of this document.
|
Sets the root element node of this document.
|
||||||
|
|
||||||
|
@@ -402,6 +402,56 @@ bool wxXmlNode::IsWhitespaceOnly() const
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// wxXmlDoctype
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void wxXmlDoctype::Clear()
|
||||||
|
{
|
||||||
|
m_rootName.clear();
|
||||||
|
m_systemId.clear();
|
||||||
|
m_publicId.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString wxXmlDoctype::GetFullString() const
|
||||||
|
{
|
||||||
|
wxString content;
|
||||||
|
if ( !m_rootName.empty() )
|
||||||
|
{
|
||||||
|
content = m_rootName;
|
||||||
|
|
||||||
|
if ( !m_publicId.empty() )
|
||||||
|
{
|
||||||
|
content << wxS(" PUBLIC \"") << m_publicId << wxS("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !m_systemId.empty() )
|
||||||
|
{
|
||||||
|
if ( m_publicId.empty() )
|
||||||
|
content << wxS(" SYSTEM");
|
||||||
|
|
||||||
|
// Prefer to use double quotes, but switch to single ones if a
|
||||||
|
// double quote appears inside the string to be quoted.
|
||||||
|
wxString quote;
|
||||||
|
if ( m_systemId.find('\"') == wxString::npos )
|
||||||
|
quote = wxS('"');
|
||||||
|
else if ( m_systemId.find('\'') == wxString::npos )
|
||||||
|
quote = wxS('\'');
|
||||||
|
else // It's an error if we can't use either kind of quotes.
|
||||||
|
return wxString();
|
||||||
|
|
||||||
|
content << wxS(' ') << quote << m_systemId << quote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxXmlDoctype::IsValid() const
|
||||||
|
{
|
||||||
|
return !GetFullString().empty();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// wxXmlDocument
|
// wxXmlDocument
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -452,6 +502,7 @@ void wxXmlDocument::DoCopy(const wxXmlDocument& doc)
|
|||||||
m_encoding = doc.m_encoding;
|
m_encoding = doc.m_encoding;
|
||||||
#endif
|
#endif
|
||||||
m_fileEncoding = doc.m_fileEncoding;
|
m_fileEncoding = doc.m_fileEncoding;
|
||||||
|
m_doctype = doc.m_doctype;
|
||||||
|
|
||||||
if (doc.m_docNode)
|
if (doc.m_docNode)
|
||||||
m_docNode = new wxXmlNode(*doc.m_docNode);
|
m_docNode = new wxXmlNode(*doc.m_docNode);
|
||||||
@@ -607,6 +658,7 @@ struct wxXmlParsingContext
|
|||||||
node(NULL),
|
node(NULL),
|
||||||
lastChild(NULL),
|
lastChild(NULL),
|
||||||
lastAsText(NULL),
|
lastAsText(NULL),
|
||||||
|
doctype(NULL),
|
||||||
removeWhiteOnlyNodes(false)
|
removeWhiteOnlyNodes(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -617,6 +669,7 @@ struct wxXmlParsingContext
|
|||||||
wxXmlNode *lastAsText; // the last _text_ child of "node"
|
wxXmlNode *lastAsText; // the last _text_ child of "node"
|
||||||
wxString encoding;
|
wxString encoding;
|
||||||
wxString version;
|
wxString version;
|
||||||
|
wxXmlDoctype *doctype;
|
||||||
bool removeWhiteOnlyNodes;
|
bool removeWhiteOnlyNodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -747,6 +800,21 @@ static void PIHnd(void *userData, const char *target, const char *data)
|
|||||||
ctx->lastAsText = NULL;
|
ctx->lastAsText = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void StartDoctypeHnd(void *userData, const char *doctypeName,
|
||||||
|
const char *sysid, const char *pubid,
|
||||||
|
int WXUNUSED(has_internal_subset))
|
||||||
|
{
|
||||||
|
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
|
||||||
|
|
||||||
|
*ctx->doctype = wxXmlDoctype(CharToString(ctx->conv, doctypeName),
|
||||||
|
CharToString(ctx->conv, sysid),
|
||||||
|
CharToString(ctx->conv, pubid));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EndDoctypeHnd(void *WXUNUSED(userData))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void DefaultHnd(void *userData, const char *s, int len)
|
static void DefaultHnd(void *userData, const char *s, int len)
|
||||||
{
|
{
|
||||||
// XML header:
|
// XML header:
|
||||||
@@ -819,6 +887,7 @@ bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding, int fl
|
|||||||
if ( encoding.CmpNoCase(wxS("UTF-8")) != 0 )
|
if ( encoding.CmpNoCase(wxS("UTF-8")) != 0 )
|
||||||
ctx.conv = new wxCSConv(encoding);
|
ctx.conv = new wxCSConv(encoding);
|
||||||
#endif
|
#endif
|
||||||
|
ctx.doctype = &m_doctype;
|
||||||
ctx.removeWhiteOnlyNodes = (flags & wxXMLDOC_KEEP_WHITESPACE_NODES) == 0;
|
ctx.removeWhiteOnlyNodes = (flags & wxXMLDOC_KEEP_WHITESPACE_NODES) == 0;
|
||||||
ctx.parser = parser;
|
ctx.parser = parser;
|
||||||
ctx.node = root;
|
ctx.node = root;
|
||||||
@@ -829,6 +898,7 @@ bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding, int fl
|
|||||||
XML_SetCdataSectionHandler(parser, StartCdataHnd, EndCdataHnd);
|
XML_SetCdataSectionHandler(parser, StartCdataHnd, EndCdataHnd);
|
||||||
XML_SetCommentHandler(parser, CommentHnd);
|
XML_SetCommentHandler(parser, CommentHnd);
|
||||||
XML_SetProcessingInstructionHandler(parser, PIHnd);
|
XML_SetProcessingInstructionHandler(parser, PIHnd);
|
||||||
|
XML_SetDoctypeDeclHandler(parser, StartDoctypeHnd, EndDoctypeHnd);
|
||||||
XML_SetDefaultHandler(parser, DefaultHnd);
|
XML_SetDefaultHandler(parser, DefaultHnd);
|
||||||
XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL);
|
XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL);
|
||||||
|
|
||||||
@@ -1133,6 +1203,17 @@ bool wxXmlDocument::Save(wxOutputStream& stream, int indentstep) const
|
|||||||
);
|
);
|
||||||
bool rc = OutputString(stream, dec, convMem.get(), convFile.get());
|
bool rc = OutputString(stream, dec, convMem.get(), convFile.get());
|
||||||
|
|
||||||
|
if ( rc )
|
||||||
|
{
|
||||||
|
const wxString doctype = m_doctype.GetFullString();
|
||||||
|
if ( !doctype.empty() )
|
||||||
|
{
|
||||||
|
rc = OutputString(stream,
|
||||||
|
wxS("<!DOCTYPE ") + doctype + wxS(">\n"),
|
||||||
|
convMem.get(), convFile.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wxXmlNode *node = GetDocumentNode();
|
wxXmlNode *node = GetDocumentNode();
|
||||||
if ( node )
|
if ( node )
|
||||||
node = node->GetChildren();
|
node = node->GetChildren();
|
||||||
|
@@ -82,6 +82,8 @@ private:
|
|||||||
CPPUNIT_TEST( AppendToProlog );
|
CPPUNIT_TEST( AppendToProlog );
|
||||||
CPPUNIT_TEST( SetRoot );
|
CPPUNIT_TEST( SetRoot );
|
||||||
CPPUNIT_TEST( CopyNode );
|
CPPUNIT_TEST( CopyNode );
|
||||||
|
CPPUNIT_TEST( CopyDocument );
|
||||||
|
CPPUNIT_TEST( Doctype );
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
void InsertChild();
|
void InsertChild();
|
||||||
@@ -94,6 +96,8 @@ private:
|
|||||||
void AppendToProlog();
|
void AppendToProlog();
|
||||||
void SetRoot();
|
void SetRoot();
|
||||||
void CopyNode();
|
void CopyNode();
|
||||||
|
void CopyDocument();
|
||||||
|
void Doctype();
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(XmlTestCase);
|
wxDECLARE_NO_COPY_CLASS(XmlTestCase);
|
||||||
};
|
};
|
||||||
@@ -207,6 +211,7 @@ void XmlTestCase::LoadSave()
|
|||||||
|
|
||||||
const char *xmlTextProlog =
|
const char *xmlTextProlog =
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<!DOCTYPE resource PUBLIC \"Public-ID\" 'System\"ID\"'>\n"
|
||||||
"<!-- Prolog comment -->\n"
|
"<!-- Prolog comment -->\n"
|
||||||
"<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
|
"<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
|
||||||
"<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
|
"<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
|
||||||
@@ -507,3 +512,103 @@ void XmlTestCase::CopyNode()
|
|||||||
;
|
;
|
||||||
CPPUNIT_ASSERT_EQUAL( xmlTextResult, sos.GetString() );
|
CPPUNIT_ASSERT_EQUAL( xmlTextResult, sos.GetString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmlTestCase::CopyDocument()
|
||||||
|
{
|
||||||
|
const char *xmlText =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<!DOCTYPE resource PUBLIC \"Public-ID\" \"System'ID'\">\n"
|
||||||
|
"<!-- 1st prolog entry -->\n"
|
||||||
|
"<root>\n"
|
||||||
|
" <first>Text</first>\n"
|
||||||
|
" <second/>\n"
|
||||||
|
"</root>\n"
|
||||||
|
;
|
||||||
|
wxXmlDocument doc1;
|
||||||
|
wxStringInputStream sis(xmlText);
|
||||||
|
CPPUNIT_ASSERT( doc1.Load(sis) );
|
||||||
|
|
||||||
|
wxXmlDocument doc2 = doc1;
|
||||||
|
|
||||||
|
wxStringOutputStream sos;
|
||||||
|
CPPUNIT_ASSERT(doc2.Save(sos));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL( xmlText, sos.GetString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void XmlTestCase::Doctype()
|
||||||
|
{
|
||||||
|
const char *xmlText =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<!DOCTYPE root PUBLIC \"Public-ID\" 'System\"ID\"'>\n"
|
||||||
|
"<root>\n"
|
||||||
|
" <content/>\n"
|
||||||
|
"</root>\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
wxStringInputStream sis(xmlText);
|
||||||
|
wxXmlDocument doc;
|
||||||
|
CPPUNIT_ASSERT( doc.Load(sis) );
|
||||||
|
|
||||||
|
wxXmlDoctype dt = doc.GetDoctype();
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "root", dt.GetRootName() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "System\"ID\"", dt.GetSystemId() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "Public-ID", dt.GetPublicId() );
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT( dt.IsValid() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "root PUBLIC \"Public-ID\" 'System\"ID\"'", dt.GetFullString() );
|
||||||
|
dt = wxXmlDoctype( dt.GetRootName(), dt.GetSystemId() );
|
||||||
|
CPPUNIT_ASSERT( dt.IsValid() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "root SYSTEM 'System\"ID\"'", dt.GetFullString() );
|
||||||
|
dt = wxXmlDoctype( dt.GetRootName() );
|
||||||
|
CPPUNIT_ASSERT( dt.IsValid() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "root", dt.GetFullString() );
|
||||||
|
|
||||||
|
doc.SetDoctype(dt);
|
||||||
|
wxStringOutputStream sos;
|
||||||
|
CPPUNIT_ASSERT(doc.Save(sos));
|
||||||
|
const char *xmlText1 =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<!DOCTYPE root>\n"
|
||||||
|
"<root>\n"
|
||||||
|
" <content/>\n"
|
||||||
|
"</root>\n"
|
||||||
|
;
|
||||||
|
CPPUNIT_ASSERT_EQUAL( xmlText1, sos.GetString() );
|
||||||
|
|
||||||
|
doc.SetDoctype(wxXmlDoctype());
|
||||||
|
wxStringOutputStream sos2;
|
||||||
|
CPPUNIT_ASSERT(doc.Save(sos2));
|
||||||
|
const char *xmlText2 =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<root>\n"
|
||||||
|
" <content/>\n"
|
||||||
|
"</root>\n"
|
||||||
|
;
|
||||||
|
CPPUNIT_ASSERT_EQUAL( xmlText2, sos2.GetString() );
|
||||||
|
|
||||||
|
doc.SetDoctype(wxXmlDoctype("root", "Sys'id"));
|
||||||
|
wxStringOutputStream sos3;
|
||||||
|
CPPUNIT_ASSERT(doc.Save(sos3));
|
||||||
|
const char *xmlText3 =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<!DOCTYPE root SYSTEM \"Sys'id\">\n"
|
||||||
|
"<root>\n"
|
||||||
|
" <content/>\n"
|
||||||
|
"</root>\n"
|
||||||
|
;
|
||||||
|
CPPUNIT_ASSERT_EQUAL( xmlText3, sos3.GetString() );
|
||||||
|
|
||||||
|
dt = wxXmlDoctype( "", "System\"ID\"", "Public-ID" );
|
||||||
|
CPPUNIT_ASSERT( !dt.IsValid() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "", dt.GetFullString() );
|
||||||
|
// Strictly speaking, this is illegal for XML but is legal for SGML.
|
||||||
|
dt = wxXmlDoctype( "root", "", "Public-ID" );
|
||||||
|
CPPUNIT_ASSERT( dt.IsValid() );
|
||||||
|
CPPUNIT_ASSERT_EQUAL( "root PUBLIC \"Public-ID\"", dt.GetFullString() );
|
||||||
|
|
||||||
|
// Using both single and double quotes in system ID is not allowed.
|
||||||
|
dt = wxXmlDoctype( "root", "O'Reilly (\"editor\")", "Public-ID" );
|
||||||
|
CPPUNIT_ASSERT( !dt.IsValid() );
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user