bool CXmlManager::_Parse() { _ReserveElement(); // Reserve index 0 for errors ::ZeroMemory(m_szErrorMsg, sizeof(m_szErrorMsg)); ::ZeroMemory(m_szErrorXML, sizeof(m_szErrorXML)); LPTSTR pstrXML = m_pstrXML; return _Parse(pstrXML, 0); }
bool CMarkup::_Parse() { _ReserveElement(); // Reserve index 0 for errors ::ZeroMemory(m_szErrorMsg, sizeof(m_szErrorMsg)); ::ZeroMemory(m_szErrorXML, sizeof(m_szErrorXML)); wchar_t* pstrXML = m_pstrXML; return _Parse(pstrXML, 0); }
bool CMarkup::_Parse(wchar_t*& pstrText, ULONG iParent) { _SkipWhitespace(pstrText); ULONG iPrevious = 0; for( ; ; ) { if( *pstrText == _T('\0') && iParent <= 1 ) return true; _SkipWhitespace(pstrText); if( *pstrText != _T('<') ) return _Failed(L"Expected start tag", pstrText); if( pstrText[1] == _T('/') ) return true; *pstrText++ = _T('\0'); _SkipWhitespace(pstrText); // Skip comment or processing directive if( *pstrText == _T('!') || *pstrText == _T('?') ) { wchar_t ch = *pstrText; if( *pstrText == _T('!') ) ch = _T('-'); while( *pstrText != _T('\0') && !(*pstrText == ch && *(pstrText + 1) == _T('>')) ) pstrText = ::CharNextW(pstrText); if( *pstrText != _T('\0') ) pstrText += 2; _SkipWhitespace(pstrText); continue; } _SkipWhitespace(pstrText); // Fill out element structure XMLELEMENT* pEl = _ReserveElement(); ULONG iPos = pEl - m_pElements; pEl->iStart = pstrText - m_pstrXML; pEl->iParent = iParent; pEl->iNext = pEl->iChild = 0; if( iPrevious != 0 ) m_pElements[iPrevious].iNext = iPos; else if( iParent > 0 ) m_pElements[iParent].iChild = iPos; iPrevious = iPos; // Parse name const wchar_t* pstrName = pstrText; _SkipIdentifier(pstrText); wchar_t* pstrNameEnd = pstrText; if( *pstrText == _T('\0') ) return _Failed(L"Error parsing element name", pstrText); // Parse attributes if( !_ParseAttributes(pstrText) ) return false; _SkipWhitespace(pstrText); if( pstrText[0] == _T('/') && pstrText[1] == _T('>') ) { pEl->iData = pstrText - m_pstrXML; *pstrText = _T('\0'); pstrText += 2; } else { if( *pstrText != _T('>') ) return _Failed(L"Expected start-tag closing", pstrText); // Parse node data pEl->iData = ++pstrText - m_pstrXML; wchar_t* pstrDest = pstrText; if( !_ParseData(pstrText, pstrDest, _T('<')) ) return false; // Determine type of next element if( *pstrText == _T('\0') && iParent <= 1 ) return true; if( *pstrText != _T('<') ) return _Failed(L"Expected end-tag start", pstrText); if( pstrText[0] == _T('<') && pstrText[1] != _T('/') ) { if( !_Parse(pstrText, iPos) ) return false; } if( pstrText[0] == _T('<') && pstrText[1] == _T('/') ) { *pstrDest = _T('\0'); *pstrText = _T('\0'); pstrText += 2; _SkipWhitespace(pstrText); SIZE_T cchName = pstrNameEnd - pstrName; if( wcsncmp(pstrText, pstrName, cchName) != 0 ) return _Failed(L"Unmatched closing tag", pstrText); pstrText += cchName; _SkipWhitespace(pstrText); if( *pstrText++ != _T('>') ) return _Failed(L"Unmatched closing tag", pstrText); } } *pstrNameEnd = _T('\0'); _SkipWhitespace(pstrText); } }
bool CMarkup::_Parse(LPTSTR& pstrText, ULONG iParent) { ULONG iPrevious = 0; for( ; ; ) { if( *pstrText == '\0' && iParent <= 1 ) return true; if( *pstrText != '<' ) return _Failed(_T("Expected start tag"), pstrText); if( pstrText[1] == '/' ) return true; *pstrText++ = '\0'; // Skip comment or processing directive if( *pstrText == '!' || *pstrText == '?' ) { TCHAR chEnd = *pstrText == '!' ? '-' : '?'; while( *pstrText != '\0' && !(*pstrText == chEnd && *(pstrText + 1) == '>') ) pstrText = ::CharNext(pstrText); if( *pstrText != '\0' ) pstrText += 2; _SkipWhitespace(pstrText); continue; } // Fill out element structure XMLELEMENT* pEl = _ReserveElement(); ULONG iPos = pEl - m_pElements; pEl->iStart = pstrText - m_pstrXML; pEl->iParent = iParent; pEl->iNext = pEl->iChild = 0; if( iPrevious != 0 ) m_pElements[iPrevious].iNext = iPos; else if( iParent > 0 ) m_pElements[iParent].iChild = iPos; iPrevious = iPos; // Parse name LPCTSTR pstrName = pstrText; _SkipIdentifier(pstrText); LPTSTR pstrNameEnd = pstrText; if( *pstrText == '\0' ) return _Failed(_T("Error parsing element name"), pstrText); // Parse attributes if( !_ParseAttributes(pstrText) ) return false; _SkipWhitespace(pstrText); if( pstrText[0] == '/' && pstrText[1] == '>' ) { pEl->iData = pstrText - m_pstrXML; *pstrText = '\0'; pstrText += 2; } else { if( *pstrText != '>' ) return _Failed(_T("Expected start-tag closing"), pstrText); // Parse node data pEl->iData = ++pstrText - m_pstrXML; LPTSTR pstrDest = pstrText; if( !_ParseData(pstrText, pstrDest, '<') ) return false; // Determine type of next element if( *pstrText == '\0' && iParent <= 1 ) return true; if( *pstrText != '<' ) return _Failed(_T("Expected end-tag start"), pstrText); if( pstrText[0] == '<' && pstrText[1] != '/' ) { if( !_Parse(pstrText, iPos) ) return false; } if( pstrText[0] == '<' && pstrText[1] == '/' ) { *pstrDest = '\0'; *pstrText = '\0'; pstrText += 2; SIZE_T cchName = pstrNameEnd - pstrName; if( _tcsncmp(pstrText, pstrName, cchName) != 0 ) return _Failed(_T("Unmatched closing tag"), pstrText); if( pstrText[cchName] != '>' ) return _Failed(_T("Unmatched closing tag"), pstrText); pstrText += cchName + 1; } } *pstrNameEnd = '\0'; _SkipWhitespace(pstrText); } }