#include "wx/zstream.h"
#include "wx/strconv.h"
#include "wx/scopedptr.h"
+#include "wx/versioninfo.h"
#include "expat.h" // from Expat
: m_type(type), m_name(name), m_content(content),
m_attrs(attrs), m_parent(parent),
m_children(NULL), m_next(next),
- m_lineNo(lineNo)
+ m_lineNo(lineNo),
+ m_noConversion(false)
{
if (m_parent)
{
: m_type(type), m_name(name), m_content(content),
m_attrs(NULL), m_parent(NULL),
m_children(NULL), m_next(NULL),
- m_lineNo(lineNo)
+ m_lineNo(lineNo), m_noConversion(false)
{}
wxXmlNode::wxXmlNode(const wxXmlNode& node)
m_name = node.m_name;
m_content = node.m_content;
m_lineNo = node.m_lineNo;
+ m_noConversion = node.m_noConversion;
m_children = NULL;
wxXmlNode *n = node.m_children;
return stream.IsOk();
}
-// flags for OutputStringEnt()
-enum
+enum EscapingMode
{
- XML_ESCAPE_QUOTES = 1
+ Escape_Text,
+ Escape_Attribute
};
// Same as above, but create entities first.
-// Translates '<' to "<", '>' to ">" and '&' to "&"
-bool OutputStringEnt(wxOutputStream& stream,
- const wxString& str,
- wxMBConv *convMem,
- wxMBConv *convFile,
- int flags = 0)
-{
- const size_t len = str.length();
- size_t i,
- last = 0;
- for (i = 0; i < len; i++)
- {
- wxChar c = str.GetChar(i);
- if (c == wxS('<') || c == wxS('>') ||
- (c == wxS('&') && str.substr(i+1, 4) != wxS("amp;")) ||
- ((flags & XML_ESCAPE_QUOTES) && c == wxS('"')))
- {
- if ( !OutputString(stream, str.substr(last, i - last),
- convMem, convFile) )
- return false;
+// Translates '<' to "<", '>' to ">" and so on, according to the spec:
+// http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping
+bool OutputEscapedString(wxOutputStream& stream,
+ const wxString& str,
+ wxMBConv *convMem,
+ wxMBConv *convFile,
+ EscapingMode mode)
+{
+ wxString escaped;
+ escaped.reserve(str.length());
- const char *escaped;
- switch ( c )
- {
- case wxS('<'):
- escaped = "<";
- break;
- case wxS('>'):
- escaped = ">";
- break;
- case wxS('&'):
- escaped = "&";
- break;
- case wxS('"'):
- escaped = """;
- break;
- default:
- wxFAIL_MSG( "logic error in the code" );
- return false;
- }
+ for ( wxString::const_iterator i = str.begin(); i != str.end(); ++i )
+ {
+ const wxChar c = *i;
- if ( !OutputString(stream, escaped, convMem, convFile) )
- return false;
+ switch ( c )
+ {
+ case wxS('<'):
+ escaped.append(wxS("<"));
+ break;
+ case wxS('>'):
+ escaped.append(wxS(">"));
+ break;
+ case wxS('&'):
+ escaped.append(wxS("&"));
+ break;
+ case wxS('\r'):
+ escaped.append(wxS("
"));
+ break;
+ default:
+ if ( mode == Escape_Attribute )
+ {
+ switch ( c )
+ {
+ case wxS('"'):
+ escaped.append(wxS("""));
+ break;
+ case wxS('\t'):
+ escaped.append(wxS("	"));
+ break;
+ case wxS('\n'):
+ escaped.append(wxS("
"));
+ break;
+ default:
+ escaped.append(c);
+ }
- last = i + 1;
+ }
+ else
+ {
+ escaped.append(c);
+ }
}
}
- return OutputString(stream, str.substr(last, i - last), convMem, convFile);
+ return OutputString(stream, escaped, convMem, convFile);
}
bool OutputIndentation(wxOutputStream& stream,
break;
case wxXML_TEXT_NODE:
- rc = OutputStringEnt(stream, node->GetContent(), convMem, convFile);
+ if (node->GetNoConversion())
+ {
+ stream.Write(node->GetContent().c_str(), node->GetContent().Length());
+ rc = true;
+ }
+ else
+ rc = OutputEscapedString(stream, node->GetContent(),
+ convMem, convFile,
+ Escape_Text);
break;
case wxXML_ELEMENT_NODE:
rc = OutputString(stream,
wxS(" ") + attr->GetName() + wxS("=\""),
convMem, convFile) &&
- OutputStringEnt(stream, attr->GetValue(),
- convMem, convFile,
- XML_ESCAPE_QUOTES) &&
+ OutputEscapedString(stream, attr->GetValue(),
+ convMem, convFile,
+ Escape_Attribute) &&
OutputString(stream, wxS("\""), convMem, convFile);
}
}
OutputString(stream, wxS("\n"), convMem.get(), convFile.get());
}
+/*static*/ wxVersionInfo wxXmlDocument::GetLibraryVersionInfo()
+{
+ return wxVersionInfo("expat",
+ XML_MAJOR_VERSION,
+ XML_MINOR_VERSION,
+ XML_MICRO_VERSION);
+}
+
#endif // wxUSE_XML