Click here to Skip to main content
12,457,770 members (25,579 online)
Click here to Skip to main content

Stats

120.4K views
5K downloads
71 bookmarked
Posted

Import/Export registry sections as XML

, 21 Jan 2003
Export registry sections as XML to simplify registry diffs
ReleaseMFCdll
registryasxml.exe
Release
registryasxml.exe
registryxml.dsp
registryxml.dsw
res
Icon_Anchor.jpg
Icon_Form.jpg
Icon_Frame.jpg
Icon_Media.jpg
Icon_Root.jpg
ImageList.bmp
ImageList256.bmp
registryxml.ico
RegistryxmlDoc.ico
TocImageList.bmp
Toolbar.bmp
registryxml.opt
registryxml.plg
registryxml.suo
registryasxml.exe
registryasxml.exe
registryxml.dsp
registryxml.dsw
Icon_Anchor.jpg
Icon_Form.jpg
Icon_Frame.jpg
Icon_Media.jpg
Icon_Root.jpg
ImageList.bmp
ImageList256.bmp
registryxml.ico
RegistryxmlDoc.ico
TocImageList.bmp
Toolbar.bmp
#include "stdafx.h"
#include "xmlreader.h"




XmlReader::XmlReader()
{
	Init();
}
XmlReader::~XmlReader()
{
}
void XmlReader::Init()
{
	m_bFileOpen = FALSE;
	ShowMsgBoxOnError(FALSE);
}
BOOL XmlReader::Open(CString &szFilename)
{
	if (m_bFileOpen)
		return TRUE;

	m_szFilename = szFilename;

	return TRUE;
}
BOOL XmlReader::ReadString()
{
	if (!m_bFileOpen) // open file for reading
	{
		m_bFileOpen = m_File.Open( (LPCTSTR)m_szFilename, CFile::modeRead | CFile::shareDenyNone );
		m_nCursor = -1;
		m_nbLines = 0;
		m_bCurInsideNode = m_bCurInsideComment = m_bCurInsideAttrib = m_bCurInsideContent = m_bCurInsideCDATA = FALSE;
		m_szLastError.Empty();
		m_szCurNodeName.Empty();
		m_szCurNodeContent.Empty();
		m_szCurAttribName.Empty();
		m_szCurAttribValue.Empty();
		m_szCurPInstruction.Empty();
	}
	if (!m_bFileOpen)
		return FALSE;

	BOOL bResult = TRUE;

	if (m_nCursor==-1)
	{
		m_szContent.Empty();
		bResult = m_File.ReadString(m_szContent);
		m_nCursor = 0;
		m_nbLines++;
	}

	if (bResult && !ParseContent())
	{
		CString s;
		s.Format("Parse error in line %d : (%s)", m_nbLines, m_szLastError.GetBuffer(0) );
		m_szLastError = s;

		if (m_bShowMsgBoxOnError)
			AfxMessageBox(s);

		bResult = FALSE;
	}

	return bResult;
}
BOOL XmlReader::Close()
{
	if (m_bFileOpen)
		m_File.Close();
	Init();

	return TRUE;
}



void XmlReader::ShowMsgBoxOnError(BOOL bShow)
{
	m_bShowMsgBoxOnError = bShow;
}


NODETYPE XmlReader::GetNodeType()
{
	return m_nCurNodeType;
}

void XmlReader::GetNodeName(/*out*/CString &szName)
{
	szName = m_szCurNodeName;
}

void XmlReader::GetAttrib(/*out*/CString &szName, /*out*/CString &szValue)
{
	szName = m_szCurAttribName;
	szValue = m_szCurAttribValue;
}

void XmlReader::GetNodeContent(/*out*/CString &szContent)
{
	szContent = m_szCurNodeContent;
}


void XmlReader::GetPInstruction(/*out*/CString &szName)
{
	szName = m_szCurPInstruction;
}

long XmlReader::GetCurrentLine()
{
	return m_nbLines;
}


void XmlReader::GetLastError(/*out*/CString &szErrorDescription) // if any
{
	szErrorDescription = m_szLastError;
}


BOOL XmlReader::ParseContent()
{
	m_nCurNodeType = NODETYPE_NA;

	long i = m_nCursor;
	long imax = m_szContent.GetLength()-1;

	if (i>imax)
	{
		m_nCursor = -1; // force next string to be read from file
		return TRUE;
	}

	CString szTemp = m_szContent.GetBuffer(0)+i;

	// pass spaces if we are inside a <...> and not yet processing an attribute value
	while ( (i<=imax) && 
			(m_bCurInsideNode && !m_bCurInsideAttrib) && 
			(m_szContent.GetAt(i)==' ' || m_szContent.GetAt(i)==0x0A || m_szContent.GetAt(i)==0x0D) )
		i++;

	if (i>imax)
	{
		m_nCursor = -1; // force next string to be read from file
		return TRUE;
	}


	// are we inside a comment ?
	if (m_bCurInsideComment)
	{
		while ( (i<=imax-2) && 
			!(m_szContent.GetAt(i)=='-' && m_szContent.GetAt(i+1)=='-' && m_szContent.GetAt(i+2)=='>') )
			i++;

		if (i<=imax-2) // found an end-comment
		{
			m_nCurNodeType = NODETYPE_NA; // tell user we have nothing to provide him with
			m_nCursor = i+2+1;

			// after '-->' we are automatically within a content
			m_bCurInsideNode = m_bCurInsideAttrib = m_bCurInsideComment = m_bCurInsideCDATA = FALSE;
			m_bCurInsideContent = TRUE;
			m_szCurNodeContent.Empty();

			return TRUE;
		}
		else // we still are inside an comment
		{
			m_nCurNodeType = NODETYPE_COMMENT;
			m_nCursor = imax+1; // force next string to be read
			return TRUE;
		}
	}


	// are we inside a CDATA section ?
	if (m_bCurInsideCDATA)
	{
		while ( (i<=imax-2) && 
			!(m_szContent.GetAt(i)==']' && m_szContent.GetAt(i+1)==']' && m_szContent.GetAt(i+2)=='>') )
			i++;

		if (i<=imax-2) // found an end-comment
		{
			m_nCurNodeType = NODETYPE_NA; // tell user we have nothing to provide him with
			m_nCursor = i+2+1;

			// after ']]>' we are automatically within a content
			m_bCurInsideNode = m_bCurInsideAttrib = m_bCurInsideComment = m_bCurInsideCDATA = FALSE;
			m_bCurInsideContent = TRUE;
			m_szCurNodeContent.Empty();

			return TRUE;
		}
		else // we still are inside an CDATA section
		{
			m_nCurNodeType = NODETYPE_CDATA;
			m_nCursor = imax+1; // force next string to be read
			return TRUE;
		}
	}


	if (m_bCurInsideAttrib) // extracting the attrib value, possibly in multiple passes
	{
		if ( m_szCurAttribValue.IsEmpty() )
		{
			// pass EOL
			while ( (i<=imax) && (m_szContent.GetAt(i)==' ' || m_szContent.GetAt(i)==0x0A || m_szContent.GetAt(i)==0x0D) )
				i++;

			if (i>imax)
			{
				m_nCurNodeType = NODETYPE_NA;
				m_nCursor = i;
				return TRUE;
			}

			char quotechar = m_szContent.GetAt(i++);

			m_szCurAttribValue += quotechar; // start with something whatsoever!
			// in fact, we don't check the quotechar is an actual quotechar, ie " or '

			m_nCurNodeType = NODETYPE_NA;
			m_nCursor = i;
			return TRUE;
		}
		else
		{

			long ibegin = i;

			// pass until we find spaces or EOL or >
			while ( (i<=imax) && m_szContent.GetAt(i)!='\"'
							  && m_szContent.GetAt(i)!='\''
							  && m_szContent.GetAt(i)!=0x0A
							  && m_szContent.GetAt(i)!=0x0D
							  && m_szContent.GetAt(i)!='>') 
				i++;

			// TODO : properly manage the case of a multiple-line attrib-value
			// (we should in this case return a N/A nodetype as long as we haven't
			// encountered the ending quotechar, while buffering all the chars in
			// the szAttribValue member).

			long iend = i;

			m_szCurAttribValue += m_szContent.Mid(ibegin, iend-ibegin);

			if (i>imax)
			{ // don't forget to add the EOL as well
				m_szCurAttribValue += "\r\n";

				m_nCurNodeType = NODETYPE_NA;
				m_nCursor = i;
				return TRUE;
			}

			// and remove the prefixed quote char
			while ( !m_szCurAttribValue.IsEmpty() && 
					(m_szCurAttribValue.GetAt(0)=='\"' || m_szCurAttribValue.GetAt(0)=='\'') )
			{
				m_szCurAttribValue = m_szCurAttribValue.Right( m_szCurAttribValue.GetLength()-1 );
			}

			m_nCurNodeType = NODETYPE_ATTRIB;
			m_bCurInsideAttrib = FALSE;

			if ( m_szContent.GetAt(i)!='>' )
				i++; // pass ending quote char

			m_nCursor = i;
			return TRUE;
		}

	} // end if m_bCurInsideAttrib==TRUE


	if (m_bCurInsideContent)
	{
		long ibegin = i;

		// pass until we find spaces or EOL or >
		while ( (i<=imax) && m_szContent.GetAt(i)!=0x0A
						  && m_szContent.GetAt(i)!=0x0D
						  && m_szContent.GetAt(i)!='<')
			i++;

		long iend = i;

		if ( (i<=imax) && m_szContent.GetAt(i)=='<')
			m_bCurInsideContent = FALSE;

		m_szCurNodeContent = m_szContent.Mid(ibegin, iend-ibegin);
		if (m_szCurNodeContent.IsEmpty())
			m_nCurNodeType = NODETYPE_NA;	
		else
			m_nCurNodeType = NODETYPE_CONTENT;

		m_nCursor = i;
		return TRUE;

	} // end if (m_bCurInsideContent)

	//
	char c = m_szContent.GetAt(i);

	// a node ?
	if (c=='<')
	{
		if (m_bCurInsideNode) // error, we were already inside one
		{
			m_szLastError = IDS_BADBEGINNODESYMBOL;
			return FALSE;
		}

		m_bCurInsideNode = TRUE;
		m_bCurInsideAttrib = m_bCurInsideContent = m_bCurInsideComment = m_bCurInsideCDATA = FALSE;

		i++;

		// pass spaces
		while ( m_szContent.GetAt(i)==' ' || m_szContent.GetAt(i)==0x0A || m_szContent.GetAt(i)==0x0D)
			i++;

		if (i>imax)
		{
			m_szLastError = IDS_NOBEGINNODESYMBOLINEOL;
			return FALSE;
		}

		// here we have either a node name, a PI, or a begin comment
		if (imax-i>=2) // is it a begin comment ? ( <!-- )
		{
			if ( m_szContent.GetAt(i+0)=='!' &&
				 m_szContent.GetAt(i+1)=='-' &&
				 m_szContent.GetAt(i+2)=='-')
			{
				m_nCurNodeType = NODETYPE_COMMENT;
				m_bCurInsideComment = TRUE;

				i+=3; // go to actual comment content

				m_nCursor = i;
				return TRUE;
			}
		}

		if (imax-i>=7) // is it a begin cdatasection ? ( <![CDATA[ )
		{
			if ( m_szContent.GetAt(i+0)=='!' &&
				 m_szContent.GetAt(i+1)=='[' &&
				 m_szContent.GetAt(i+2)=='C' &&
				 m_szContent.GetAt(i+3)=='D' &&
				 m_szContent.GetAt(i+4)=='A' &&
				 m_szContent.GetAt(i+5)=='T' &&
				 m_szContent.GetAt(i+6)=='A' &&
				 m_szContent.GetAt(i+7)=='[')
			{
				m_nCurNodeType = NODETYPE_CDATA;
				m_bCurInsideCDATA = TRUE;

				i+=8; // go to actual cdata section content

				m_nCursor = i;
				return TRUE;
			}
		}


		// the node name begins at position i
		long ibegin = i;

		// pass until we find spaces or EOL or >
		while ( (i<=imax) && m_szContent.GetAt(i)!=' ' 
						  && m_szContent.GetAt(i)!=0x0A
						  && m_szContent.GetAt(i)!=0x0D
						  && (m_szContent.GetAt(i)!='/' || (i==ibegin)) // don't forget empty elements (for instance <br/>)
						  && m_szContent.GetAt(i)!='>')
			i++;

		long iend = i;
	
		m_szCurNodeName = m_szContent.Mid(ibegin, iend-ibegin);
		if (m_szCurNodeName.IsEmpty())
		{
			m_szLastError = IDS_EMPTYELEMENTNAME;
			return FALSE;
		}


		if (m_szCurNodeName.GetAt(0)=='?' || m_szCurNodeName.GetAt(0)=='!')
		{
			m_nCurNodeType = NODETYPE_PI;
			m_szCurPInstruction = m_szCurNodeName;
			m_szCurNodeName.Empty(); // erase the PI instruction so it does not appear as a node name
		}
		else if (m_szCurNodeName.GetAt(0)=='/')
		{
			m_nCurNodeType = NODETYPE_ENDELEMENT;
			m_szCurNodeName = m_szCurNodeName.Right( m_szCurNodeName.GetLength()-1 ); // remove /
		}
		else
			m_nCurNodeType = NODETYPE_BEGINELEMENT;

		m_nCursor = i;
		return TRUE;

	}
	else // >, or ?, or content or attribute
	{
		if (c=='?')
		{
			m_nCurNodeType = NODETYPE_NA;
			m_nCursor = i+1;
			return TRUE;
		}
		else if (c=='/')
		{
			i++;

			// pass node name
			long ibegin = i;

			// pass until we find spaces or EOL or >
			while ( (i<=imax) && m_szContent.GetAt(i)!=' ' 
							  && m_szContent.GetAt(i)!=0x0A
							  && m_szContent.GetAt(i)!=0x0D
							  && m_szContent.GetAt(i)!='>')
				i++;

			long iend = i;
		
			m_nCurNodeType = NODETYPE_ENDELEMENT;

			m_nCursor = i;
			return TRUE;
		}
		else if (c=='>')
		{
			m_bCurInsideNode = m_bCurInsideAttrib = FALSE;
			m_bCurInsideContent = TRUE;
			m_szCurNodeContent.Empty();
			m_nCurNodeType = NODETYPE_NA;
			m_nCursor = i+1;
			return TRUE;
		}

		if (m_bCurInsideNode) // attributes
		{

			if (!m_bCurInsideAttrib)
			{
				if (c=='=')
				{
					m_nCurNodeType = NODETYPE_NA;
					m_bCurInsideAttrib = TRUE; // enable extraction of the associated attribute value

					i++; // pass '=' symbol

					m_nCursor = i;
					return TRUE;
				}

				// get attribute name
				long ibegin = i;

				// pass until we find spaces or EOL or >
				while ( (i<=imax) && m_szContent.GetAt(i)!=' '
								  && m_szContent.GetAt(i)!=0x0A
								  && m_szContent.GetAt(i)!=0x0D
								  && m_szContent.GetAt(i)!='='
								  && m_szContent.GetAt(i)!='>') // check against > is just for safety
					i++;

				long iend = i;

				m_szCurAttribName = m_szContent.Mid(ibegin, iend-ibegin);
				if (m_szCurAttribName.IsEmpty())
				{
					m_szLastError = IDS_MISSINGATTRIBNAME;
					return FALSE;
				}

				m_szCurAttribValue.Empty(); // make sure the attrib value is empty for the moment
				m_nCurNodeType = NODETYPE_NA;

				m_nCursor = i;
				return TRUE;
			}

		}
	}

	// this code never executes
	m_szLastError = IDS_GENERICSYNTAXERROR;
	return FALSE;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Addicted to reverse engineering. At work, I am developing business intelligence software in a team of smart people (independent software vendor).

Need a fast Excel generation component? Try xlsgen.


You may also be interested in...

Pro
Pro
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160826.1 | Last Updated 22 Jan 2003
Article Copyright 2002 by Stephane Rodriguez.
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid