⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlwriter.cpp

📁 简单的xml解析类
💻 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("&", "&amp;");
		}
		if( text.findPos("<") != String::npos ) {
			text = text.replaceAll("<", "&lt;");
		}
		if( text.findPos(">") != String::npos ) {
			text = text.replaceAll(">", "&gt;");
		}
		if( text.findPos("\"") != String::npos ) {
			text = text.replaceAll("\"", "&quot;");
		}
		if( text.findPos("\'") != String::npos ) {
			text = text.replaceAll("\'", "&apos;");
		}

		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 + -