📄 xmlwriter.cpp
字号:
//**************************************************************************************************************************
//* Blue Xml Extension
//* Copyright (c) 2002-2004 Josh Harler
//*
//* Blue - General Purpose C++ Library
//* Copyright (c) 2002-2004 Josh Harler
//*
//* This software is provided 'as-is', without any express or implied warranty. In no event
//* will the authors be held liable for any damages arising from the use of this software.
//*
//* Permission is granted to anyone to use this software for any purpose, including commercial
//* applications, and to alter it and redistribute it freely, subject to the following restrictions:
//*
//* 1. The origin of this software must not be misrepresented; you must not claim that you
//* wrote the original software. If you use this software in a product, an acknowledgment in the
//* product documentation would be appreciated but is not required.
//*
//* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as
//* being the original software.
//*
//* 3. This notice may not be removed or altered from any source distribution.
//*
//*
//* file Blue/Extension/Xml/XmlWriter.cpp
//**
// Private Headers =========================================================================================================
// matching header
#include "XmlWriter.h"
// Extension headers
#include "Blue/Extension/Xml/DomParser.h"
// Private Defines/Enums/Typedefs/Etc ======================================================================================
// Private Classes/Structs =================================================================================================
// Private Global Variables ================================================================================================
// External Global Variables ===============================================================================================
// Private Functions =======================================================================================================
// Functions ===============================================================================================================
namespace blue {
namespace ext {
namespace xml {
// ---------------------------------------------------------------------------------------------------------------------
XmlWriter::XmlWriter() :m_output(0), m_flags(0), m_tabLevel(0), m_state(WRITING_NOTHING), m_lastNewLine(false)
{
}
// ---------------------------------------------------------------------------------------------------------------------
XmlWriter::~XmlWriter()
{
}
// ---------------------------------------------------------------------------------------------------------------------
const data::OutputStream* XmlWriter::getOutputStream() const
{
return (m_output);
}
// ---------------------------------------------------------------------------------------------------------------------
flags32_t XmlWriter::getFormatFlags() const
{
return (m_flags);
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::setOutputStream( data::OutputStream* output )
{
m_output = output;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::setFormatFlags( flags32_t flags )
{
m_flags = flags;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::startXml()
{
m_state = WRITING_TEXT;
m_lastNewLine = false;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::endXml()
{
m_state = WRITING_NOTHING;
}
// ---------------------------------------------------------------------------------------------------------------------
bool XmlWriter::hasXmlStarted() const
{
return (m_state != WRITING_NOTHING);
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::beginDocument()
{
beginProcInst($("xml"));
addProcInstAttribute($("version"), $("1.0"));
addProcInstAttribute($("encoding"), $("utf-8"));
endProcInst();
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::beginProcInst( String procinst )
{
elementCapIfNeeded();
writeTabs();
write(String("<?", String::STATIC));
write(procinst);
m_state = WRITING_PROCINST;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::addProcInstAttribute( String attribute, String value )
{
if( m_state != WRITING_PROCINST ) {
throw XmlWriterException($("Processing instruction attributes can only be added in a processing instruction"));
}
write($(" "));
write(attribute);
write($("=\""));
write(encode(value));
write($("\""));
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::endProcInst()
{
if( m_state != WRITING_PROCINST ) {
throw XmlWriterException($("Processing instruction must be opened before it can be closed"));
}
write($("?>"));
writeNewLine();
m_state = WRITING_TEXT;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::beginElement( String element )
{
elementCapIfNeeded();
if( m_state != WRITING_TEXT ) {
throw XmlWriterException("Cannot place element '" + element + "' at this position.");
}
writeTabs();
write($("<"));
write(element);
++m_tabLevel;
elementPush(element);
m_state = WRITING_ELEMENT;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::addElementAttribute( String attribute, String value )
{
if( m_state != WRITING_ELEMENT ) {
throw XmlWriterException($("Element attributes must be added before anything else in the element"));
}
write($(" "));
write(attribute);
write($("=\""));
write(encode(value));
write($("\""));
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::addText( String text )
{
elementCapIfNeeded();
if( m_elementStack.getSize() == 0 ) {
throw XmlWriterException($("Text must reside inside an element"));
}
if( text != String::null ) {
writeTabs();
write(encode(text));
writeNewLine();
}
m_state = WRITING_TEXT;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::addCDataText( String cdata )
{
elementCapIfNeeded();
if( m_elementStack.getSize() == 0 ) {
throw XmlWriterException($("CDATA text must reside inside an element"));
}
writeTabs();
write($("<![CDATA["));
write(cdata);
write($("]]>"));
writeNewLine();
m_state = WRITING_TEXT;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::endElement()
{
if( m_state == WRITING_ELEMENT ) {
write($("/"));
elementCapIfNeeded();
elementPop();
--m_tabLevel;
}
else {
if( m_state != WRITING_TEXT ) {
throw XmlWriterException($("Cannot end previous element at this position"));
}
--m_tabLevel;
writeTabs();
write($("<"));
write($("/"));
write(elementPop());
write($(">"));
writeNewLine();
}
m_state = WRITING_TEXT;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::addElement( String element, String text )
{
beginElement(element);
if( text != String::null ) {
write($(">"));
m_state = WRITING_TEXT;
if( text.findPos("\n") == String::npos ) {
write(encode(text));
}
else {
writeNewLine();
writeTabs();
write(encode(text));
writeNewLine();
}
}
endElement();
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::addComment( String comment )
{
elementCapIfNeeded();
writeTabs();
write($("<!-- "));
write(comment);
write($("-->"));
writeNewLine();
m_state = WRITING_TEXT;
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::writeDomTree( const DomNode* node )
{
if( node == 0 ) {
throw XmlWriterException($("Cannot write a null DomNode tree"));
}
switch( node->getNodeType() )
{
case DomNode::DOCUMENT: {
Array<DomNode*> nodes = node->getSubNodes();
for( int iN = 0; iN < nodes.getSize(); ++iN ) {
writeDomTree(nodes[iN]);
}
break;
}
case DomNode::ELEMENT: {
DomElementNode* element = (DomElementNode*)node;
if( element->getSubNodes().getSize() == 1 ) {
addElement(element->getName(), element->getValue());
}
else {
beginElement(element->getName());
Array<DomAttributeNode*> attributes = element->getAttributeNodes();
for( int iA = 0; iA < attributes.getSize(); ++iA ) {
DomAttributeNode* attribute = attributes[iA];
addElementAttribute(attribute->getName(), attribute->getValue());
}
Array<DomNode*> nodes = element->getSubNodes();
for( int iN = 0; iN < nodes.getSize(); ++iN ) {
if( nodes[iN]->getNodeType() != DomNode::ATTRIBUTE ) {
writeDomTree(nodes[iN]);
}
}
endElement();
}
break;
}
case DomNode::TEXT: {
addText(node->getValue());
break;
}
case DomNode::CDATA: {
addCDataText(node->getValue());
break;
}
case DomNode::PROC_INST: {
beginProcInst(node->getName());
Array<DomNode*> nodes = node->getSubNodes();
for( int iN = 0; iN < nodes.getSize(); ++iN ) {
if( nodes[iN]->getNodeType() == DomNode::ATTRIBUTE ) {
DomAttributeNode* attribute = (DomAttributeNode*)nodes[iN];
addProcInstAttribute(attribute->getName(), attribute->getValue());
}
}
endProcInst();
break;
}
case DomNode::COMMENT: {
addComment(node->getValue());
break;
}
}
}
// ---------------------------------------------------------------------------------------------------------------------
String XmlWriter::encode( String text )
{
if( text.findPos("&") != String::npos ) {
text = text.replaceAll("&", "&");
}
if( text.findPos("<") != String::npos ) {
text = text.replaceAll("<", "<");
}
if( text.findPos(">") != String::npos ) {
text = text.replaceAll(">", ">");
}
if( text.findPos("\"") != String::npos ) {
text = text.replaceAll("\"", """);
}
if( text.findPos("\'") != String::npos ) {
text = text.replaceAll("\'", "'");
}
return (text);
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::elementCapIfNeeded()
{
if( m_state == WRITING_ELEMENT ) {
write( $(">") );
writeNewLine();
m_state = WRITING_TEXT;
}
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::elementPush(String element)
{
m_elementStack.append(element);
}
// ---------------------------------------------------------------------------------------------------------------------
String XmlWriter::elementPop()
{
if( m_elementStack.getSize() == 0 ) {
throw XmlWriterException($("There is no open element to end"));
}
String element = m_elementStack[m_elementStack.getSize()-1];
m_elementStack.remove(m_elementStack.getSize()-1);
return (element);
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::write( String data )
{
if( m_state == WRITING_NOTHING ) {
throw XmlWriterException($("XmlWriter cannot write until xmlStart() has been called"));
}
m_output->write(data.getAsCStr(), data.getLength());
m_lastNewLine = (data == "\n");
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::writeTabs()
{
if( !(m_flags & NO_NEWLINES) ) {
if( !(m_flags & NO_TABS) && m_lastNewLine ) {
write( String::fill(m_tabLevel, '\t') );
}
}
}
// ---------------------------------------------------------------------------------------------------------------------
void XmlWriter::writeNewLine()
{
if( !(m_flags & NO_NEWLINES) ) {
write( String("\n", String::STATIC) );
}
else {
write( String(" ", String::STATIC) );
}
}
}}} // namespaces
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -