// Markup.cpp: implementation of the CMarkup class.
//
// CMarkup Release 6.5 Lite
// Copyright (C) 1999-2003 First Objective Software, Inc. All rights reserved
// This entire notice must be retained in this source code
// Redistributing this source code requires written permission
// This software is provided "as is", with no warranty.
// Latest fixes enhancements and documentation at www.firstobject.com
#include "stdafx.h"
#include "afxconv.h"
#include "Markup.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#ifdef _MBCS
#pragma message( "Note: MBCS build (UTF-8)" )
// For UTF-8, remove _MBCS from project settings C/C++ preprocessor definitions
#endif
// Defines for Windows CE
#ifdef _WIN32_WCE
#define _tclen(p) 1
#define _tccpy(p1,p2) *(p1)=*(p2)
#endif
void CMarkup::operator=( const CMarkup& markup )
{
m_iPosParent = markup.m_iPosParent;
m_iPos = markup.m_iPos;
m_iPosChild = markup.m_iPosChild;
m_iPosFree = markup.m_iPosFree;
m_nNodeType = markup.m_nNodeType;
m_aPos.RemoveAll();
m_aPos.Append( markup.m_aPos );
m_csDoc = markup.m_csDoc;
MARKUP_SETDEBUGSTATE;
}
bool CMarkup::SetDoc( LPCTSTR szDoc )
{
// Reset indexes
m_iPosFree = 1;
ResetPos();
// Set document text
if ( szDoc )
m_csDoc = szDoc;
else
m_csDoc.Empty();
// Starting size of position array: 1 element per 64 bytes of document
// Tight fit when parsing small doc, only 0 to 2 reallocs when parsing large doc
// Start at 8 when creating new document
int nStartSize = m_csDoc.GetLength() / 64 + 8;
if ( m_aPos.GetSize() < nStartSize )
m_aPos.SetSize( nStartSize );
// Parse document
bool bWellFormed = false;
if ( m_csDoc.GetLength() )
{
m_aPos[0].Clear();
int iPos = x_ParseElem( 0 );
if ( iPos > 0 )
{
m_aPos[0].iElemChild = iPos;
bWellFormed = true;
}
}
// Clear indexes if parse failed or empty document
if ( ! bWellFormed )
{
m_aPos[0].Clear();
m_iPosFree = 1;
}
ResetPos();
// if (TRUE==bWellFormed)
// {
// AfxMessageBox("SetDoc 返回TRUE");
// }
// if (FALSE==bWellFormed)
// {
// AfxMessageBox("SetDoc 返回FALSE");
// }
return bWellFormed;
};
bool CMarkup::IsWellFormed()
{
if ( m_aPos.GetSize() && m_aPos[0].iElemChild )
return true;
return false;
}
bool CMarkup::FindElem( LPCTSTR szName )
{
// Change current position only if found
//
if ( m_aPos.GetSize() )
{
int iPos = x_FindElem( m_iPosParent, m_iPos, szName );
if ( iPos )
{
// Assign new position
x_SetPos( m_aPos[iPos].iElemParent, iPos, 0 );
return true;
}
}
return false;
}
bool CMarkup::FindChildElem( LPCTSTR szName )
{
// Change current child position only if found
//
// Shorthand: call this with no current main position
// means find child under root element
if ( ! m_iPos )
FindElem();
int iPosChild = x_FindElem( m_iPos, m_iPosChild, szName );
if ( iPosChild )
{
// Assign new position
int iPos = m_aPos[iPosChild].iElemParent;
x_SetPos( m_aPos[iPos].iElemParent, iPos, iPosChild );
return true;
}
return false;
}
CString CMarkup::GetTagName() const
{
// Return the tag name at the current main position
CString csTagName;
if ( m_iPos )
csTagName = x_GetTagName( m_iPos );
return csTagName;
}
bool CMarkup::IntoElem()
{
// If there is no child position and IntoElem is called it will succeed in release 6.3
// (A subsequent call to FindElem will find the first element)
// The following short-hand behavior was never part of EDOM and was misleading
// It would find a child element if there was no current child element position and go into it
// It is removed in release 6.3, this change is NOT backwards compatible!
// if ( ! m_iPosChild )
// FindChildElem();
if ( m_iPos && m_nNodeType == MNT_ELEMENT )
{
x_SetPos( m_iPos, m_iPosChild, 0 );
return true;
}
return false;
}
bool CMarkup::OutOfElem()
{
// Go to parent element
if ( m_iPosParent )
{
x_SetPos( m_aPos[m_iPosParent].iElemParent, m_iPosParent, m_iPos );
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////
// Private Methods
//////////////////////////////////////////////////////////////////////
int CMarkup::x_GetFreePos()
{
//
// This returns the index of the next unused ElemPos in the array
//
if ( m_iPosFree == m_aPos.GetSize() )
m_aPos.SetSize( m_iPosFree + m_iPosFree / 2 );
++m_iPosFree;
return m_iPosFree - 1;
}
int CMarkup::x_ReleasePos()
{
//
// This decrements the index of the next unused ElemPos in the array
// allowing the element index returned by GetFreePos() to be reused
//
--m_iPosFree;
return 0;
}
int CMarkup::x_ParseError( LPCTSTR szError, LPCTSTR szName )
{
if ( szName )
m_csError.Format( szError, szName );
else
m_csError = szError;
x_ReleasePos();
return -1;
}
int CMarkup::x_ParseElem( int iPosParent )
{
// This is either called by SetDoc, x_AddSubDoc, or itself recursively
// m_aPos[iPosParent].nEndL is where to start parsing for the child element
// This returns the new position if a tag is found, otherwise zero
// In all cases we need to get a new ElemPos, but release it if unused
//
int iPos = x_GetFreePos();
m_aPos[iPos].nStartL = m_aPos[iPosParent].nEndL;
m_aPos[iPos].iElemParent = iPosParent;
m_aPos[iPos].iElemChild = 0;
m_aPos[iPos].iElemNext = 0;
// Start Tag
// A loop is used to ignore all remarks tags and special tags
// i.e. <?xml version="1.0"?>, and <!-- comment here -->
// So any tag beginning with ? or ! is ignored
// Loop past ignored tags
TokenPos token( m_csDoc );
token.nNext = m_aPos[iPosParent].nEndL;
CString csName;
while ( csName.IsEmpty() )
{
// Look for left angle bracket of start tag
m_aPos[iPos].nStartL = token.nNext;
if ( ! x_FindChar( token.szDoc, m_aPos[iPos].nStartL, _T('<') ) )
return x_ParseError( _T("Element tag not found") );
// Set parent's End tag to start looking from here (or later)
m_aPos[iPosParent].nEndL = m_aPos[iPos].nStartL;
// Determine whether this is an element, or bypass other type of node
token.nNext = m_aPos[iPos].nStartL + 1;
if ( x_FindToken( token ) )
{
if ( token.bIsString )
return x_ParseError( _T("Tag starts with quote") );
_TCHAR cFirstChar = m_csDoc[token.nL];
if ( cFirstChar == _T('?') || cFirstChar == _T('!') )
{
token.nNext = m_aPos[iPos].nStartL;
if ( ! x_ParseNode(token) )
return x_ParseError( _T("Invalid node") );
}
else if ( cFirstChar != _T('/') )
{
csName = x_GetToken( token );
// Look for end of tag
if ( ! x_FindChar(token.szDoc, token.nNext, _T('>')) )
return x_ParseError( _T("End of tag not found") );
}
else
return x_ReleasePos(); // probably end tag of parent
}
else
return x_ParseError( _T("Abrupt end within tag") );
}
m_aPos[iPos].nStartR = token.nNext;
// Is ending mark within start tag, i.e. empty element?
if ( m_csDoc[m_aPos[iPos].nStartR-1] == _T('/') )
{
// Empty element
// Close tag left is set to ending mark, and right to open tag right
m_aPos[iPos].nEndL = m_aPos[iPos].nStartR-1;
m_aPos[iPos].nEndR = m_aPos[iPos].nStartR;
}
else // look for end tag
{
// Element probably has contents
// Determine where to start looking for left angle bracket of end tag
// This is done by recursively parsing the contents of this element
int iInner, iInnerPrev = 0;
m_aPos[iPos].nEndL = m_aPos[iPos].nStartR + 1;
while ( (iInner = x_ParseElem( iPos )) > 0 )
{
// Set links to iInner
if ( iInnerPrev )
m_aPos[iInnerPrev].iElemNext = iInner;
else
m_aPos[iPos].iElemChild = iInner;
iInnerPrev = iInner;
// Set offset to reflect child
m_aPos[iPos].nEndL = m_aPos[iInner].nEndR + 1;
VC 读写XML文件类库
3星 · 超过75%的资源 需积分: 9 163 浏览量
2012-04-25
09:11:39
上传
评论
收藏 10KB RAR 举报
夜里笙歌
- 粉丝: 8
- 资源: 10
最新资源
- 《软件测试训练营》学习笔记-举例注册测试用例
- 机器学习预测.rar机器学习预测.rar机器学习预测.rar
- VIS 110Nm lib ip
- 848694479200715布谷鸟配音_1.10.8.0.apk
- 基于改进粒子群算法微电网日前优化(matlab程序)
- Energy Hub Integration: Optimizing Electricity and Heat Market P
- 基于C51单片机蓝牙控制小车proteus仿真程序源码+相关技术文档资料.zip
- Integrated-Energy-Systems-with-CAES-(注释完全,可直接运行)
- PDF为英语文本绘制热区(DEMO)
- Python一种新的需求响应机制DR-VCG研究(注释完全,可直接运行)(文档加Matlab源码)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈