?? xmlwriter.cpp
字號:
//
// XMLWriter.cpp
//
// $Id: //poco/Main/XML/src/XMLWriter.cpp#5 $
//
// Copyright (c) 2004, Guenter Obiltschnig/Applied Informatics.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Redistributions in any form must be accompanied by information on
// how to obtain complete source code for this software and any
// accompanying software that uses this software. The source code
// must either be included in the distribution or be available for no
// more than the cost of distribution plus a nominal fee, and must be
// freely redistributable under reasonable conditions. For an
// executable file, complete source code means the source code for all
// modules it contains. It does not include source code for modules or
// files that typically accompany the major components of the operating
// system on which the executable file runs.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#include "XML/XMLWriter.h"
#include "XML/XMLString.h"
#include "XML/XMLException.h"
#include "SAX/AttributesImpl.h"
#include "Foundation/UTF8Encoding.h"
#include <sstream>
XML_BEGIN
const std::string XMLWriter::NEWLINE_DEFAULT;
const std::string XMLWriter::NEWLINE_CR = "\r";
const std::string XMLWriter::NEWLINE_CRLF = "\r\n";
const std::string XMLWriter::NEWLINE_LF = "\n";
const std::string XMLWriter::MARKUP_QUOTENC = """;
const std::string XMLWriter::MARKUP_APOSENC = "'";
const std::string XMLWriter::MARKUP_AMPENC = "&";
const std::string XMLWriter::MARKUP_LTENC = "<";
const std::string XMLWriter::MARKUP_GTENC = ">";
const std::string XMLWriter::MARKUP_LT = "<";
const std::string XMLWriter::MARKUP_GT = ">";
const std::string XMLWriter::MARKUP_SLASHGT = "/>";
const std::string XMLWriter::MARKUP_LTSLASH = "</";
const std::string XMLWriter::MARKUP_COLON = ":";
const std::string XMLWriter::MARKUP_EQQUOT = "=\"";
const std::string XMLWriter::MARKUP_QUOT = "\"";
const std::string XMLWriter::MARKUP_SPACE = " ";
const std::string XMLWriter::MARKUP_TAB = "\t";
const std::string XMLWriter::MARKUP_BEGIN_CDATA = "<![CDATA[";
const std::string XMLWriter::MARKUP_END_CDATA = "]]>";
#if defined(XML_UNICODE_WCHAR_T)
#define NATIVE_ENCODING Foundation::UTF16Encoding
#else
#define NATIVE_ENCODING Foundation::UTF8Encoding
#endif
XMLWriter::XMLWriter(XMLByteOutputStream& str, int options):
_pTextConverter(0),
_pInEncoding(new NATIVE_ENCODING),
_pOutEncoding(new Foundation::UTF8Encoding),
_options(options),
_encoding("UTF-8"),
_depth(-1),
_elementCount(0),
_inFragment(false),
_inCDATA(false),
_inDTD(false),
_inInternalDTD(false),
_contentWritten(false),
_unclosedStartTag(false),
_prefix(0)
{
_pTextConverter = new Foundation::OutputStreamConverter(str, *_pInEncoding, *_pOutEncoding);
setNewLine(NEWLINE_DEFAULT);
}
XMLWriter::XMLWriter(XMLByteOutputStream& str, int options, const std::string& encodingName, Foundation::TextEncoding& textEncoding):
_pTextConverter(0),
_pInEncoding(new NATIVE_ENCODING),
_pOutEncoding(0),
_options(options),
_encoding(encodingName),
_depth(-1),
_elementCount(0),
_inFragment(false),
_inCDATA(false),
_inDTD(false),
_inInternalDTD(false),
_contentWritten(false),
_unclosedStartTag(false),
_prefix(0)
{
_pTextConverter = new Foundation::OutputStreamConverter(str, *_pInEncoding, textEncoding);
setNewLine(NEWLINE_DEFAULT);
}
XMLWriter::XMLWriter(XMLByteOutputStream& str, int options, const std::string& encodingName, Foundation::TextEncoding* pTextEncoding):
_pTextConverter(0),
_pInEncoding(new NATIVE_ENCODING),
_pOutEncoding(0),
_options(options),
_encoding(encodingName),
_depth(-1),
_elementCount(0),
_inFragment(false),
_inCDATA(false),
_inDTD(false),
_inInternalDTD(false),
_contentWritten(false),
_unclosedStartTag(false),
_prefix(0)
{
if (pTextEncoding)
{
_pTextConverter = new Foundation::OutputStreamConverter(str, *_pInEncoding, *pTextEncoding);
}
else
{
_encoding = "UTF-8";
_pOutEncoding = new Foundation::UTF8Encoding;
_pTextConverter = new Foundation::OutputStreamConverter(str, *_pInEncoding, *_pOutEncoding);
}
setNewLine(NEWLINE_DEFAULT);
}
XMLWriter::~XMLWriter()
{
delete _pTextConverter;
delete _pInEncoding;
delete _pOutEncoding;
}
void XMLWriter::setDocumentLocator(const Locator* loc)
{
}
void XMLWriter::setNewLine(const std::string& newLineCharacters)
{
if (newLineCharacters.empty())
{
#if defined(_WIN32)
_newLine = NEWLINE_CRLF;
#else
_newLine = NEWLINE_LF;
#endif
}
else _newLine = newLineCharacters;
}
const std::string& XMLWriter::getNewLine() const
{
return _newLine;
}
void XMLWriter::startDocument()
{
if (_depth != -1)
throw XMLException("Cannot start a document in another document");
_inFragment = false;
_depth = 0;
_elementCount = 0;
_inDTD = false;
_inInternalDTD = false;
_prefix = 0;
if (_options & WRITE_XML_DECLARATION)
writeXMLDeclaration();
_contentWritten = true;
_namespaces.reset();
_namespaces.pushContext();
}
void XMLWriter::endDocument()
{
if (_depth > 0)
throw XMLException("Not well-formed (at least one tag has no matching end tag)");
if (_elementCount == 0)
throw XMLException("No document element");
_elementCount = 0;
_depth = -1;
}
void XMLWriter::startFragment()
{
if (_depth != -1)
throw XMLException("Cannot start a fragment in another fragment or document");
_inFragment = true;
_depth = 0;
_elementCount = 0;
_prefix = 0;
_contentWritten = true;
_namespaces.reset();
_namespaces.pushContext();
}
void XMLWriter::endFragment()
{
if (_depth > 1)
throw XMLException("Not well-formed (at least one tag has no matching end tag)");
_inFragment = false;
_elementCount = 0;
_depth = -1;
}
void XMLWriter::startElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname)
{
AttributesImpl attributes;
startElement(namespaceURI, localName, qname, attributes);
}
void XMLWriter::startElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const Attributes& attributes)
{
if (_depth == 0 && !_inFragment && _elementCount > 1)
throw XMLException("Not well-formed. Second root element found", nameToString(localName, qname));
if (_unclosedStartTag) closeStartTag();
prettyPrint();
writeStartElement(namespaceURI, localName, qname, attributes);
_elementStack.push_back(Name(qname, namespaceURI, localName));
_contentWritten = false;
++_depth;
}
void XMLWriter::endElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname)
{
if (_depth < 1)
throw XMLException("No unclosed tag");
if (!_elementStack.back().equalsWeakly(qname, namespaceURI, localName))
throw XMLException("End tag does not match start tag", nameToString(localName, qname));
_elementStack.pop_back();
--_depth;
if (!_unclosedStartTag) prettyPrint();
writeEndElement(namespaceURI, localName, qname);
_contentWritten = false;
if (_depth == 0)
writeNewLine();
}
void XMLWriter::emptyElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname)
{
AttributesImpl attributes;
emptyElement(namespaceURI, localName, qname, attributes);
}
void XMLWriter::emptyElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const Attributes& attributes)
{
if (_depth == 0 && _elementCount > 1)
throw XMLException("Not well-formed. Second root element found.");
if (_unclosedStartTag) closeStartTag();
prettyPrint();
writeStartElement(namespaceURI, localName, qname, attributes);
_contentWritten = false;
}
void XMLWriter::characters(const XMLChar ch[], int start, int length)
{
if (_unclosedStartTag) closeStartTag();
_contentWritten = length > 0;
if (_inCDATA)
{
while (length-- > 0) writeXML(ch[start++]);
}
else
{
while (length-- > 0)
{
XMLChar c = ch[start++];
switch (c)
{
case '"': writeMarkup(MARKUP_QUOTENC); break;
case '\'': writeMarkup(MARKUP_APOSENC); break;
case '&': writeMarkup(MARKUP_AMPENC); break;
case '<': writeMarkup(MARKUP_LTENC); break;
case '>': writeMarkup(MARKUP_GTENC); break;
default:
if (c >= 0 && c < 32)
{
if (c == '\t' || c == '\r' || c == '\n')
writeXML(c);
else
throw XMLException("Invalid character token.");
}
else writeXML(c);
}
}
}
}
void XMLWriter::characters(const XMLString& str)
{
characters(str.data(), 0, (int) str.length());
}
void XMLWriter::rawCharacters(const XMLString& str)
{
writeXML(str);
}
void XMLWriter::ignorableWhitespace(const XMLChar ch[], int start, int length)
{
characters(ch, start, length);
}
void XMLWriter::processingInstruction(const XMLString& target, const XMLString& data)
{
if (_unclosedStartTag) closeStartTag();
prettyPrint();
writeMarkup("<?");
writeXML(target);
if (!data.empty())
{
writeMarkup(MARKUP_SPACE);
writeXML(data);
}
writeMarkup("?>");
if (_depth == 0)
writeNewLine();
}
void XMLWriter::dataElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname,
const XMLString& data,
const XMLString& attr1, const XMLString& value1,
const XMLString& attr2, const XMLString& value2,
const XMLString& attr3, const XMLString& value3)
{
static const XMLString CDATA = toXMLString("CDATA");
AttributesImpl attributes;
if (!attr1.empty()) attributes.addAttribute(XMLString(), XMLString(), attr1, CDATA, value1);
if (!attr2.empty()) attributes.addAttribute(XMLString(), XMLString(), attr2, CDATA, value2);
if (!attr3.empty()) attributes.addAttribute(XMLString(), XMLString(), attr3, CDATA, value3);
if (data.empty())
{
emptyElement(namespaceURI, localName, qname, attributes);
}
else
{
startElement(namespaceURI, localName, qname, attributes);
characters(data);
endElement(namespaceURI, localName, qname);
}
}
void XMLWriter::startPrefixMapping(const XMLString& prefix, const XMLString& namespaceURI)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -