/* License Sometimes I get email about license of XMLite. You can use/modify/redistribute XMLite for commercial/noncomercial. But please give me thanks email with your project information.Then I will be happy and add it to references of XMLite. If you fix or update XMLite then give it to me for all to have. Thanks. */ #include "stdafx.h" #include "XMLite.h" #include #include #include static const TCHAR chXMLTagOpen = '<'; static const TCHAR chXMLTagClose = '>'; static const TCHAR chXMLTagPre = '/'; static const TCHAR chXMLEscape = '\\'; // for value field escape static const TCHAR szXMLPIOpen[] = _T(""); static const TCHAR szXMLCommentOpen[] = _T(""); static const TCHAR szXMLCDATAOpen[] = _T(""); static const XENTITY x_EntityTable[] = { { '&', _T("&"), 5 } , { '\"', _T("""), 6 } , { '\'', _T("'"), 6 } , { '<', _T("<"), 4 } , { '>', _T(">"), 4 } }; PARSEINFO piDefault; DISP_OPT optDefault; XENTITYS entityDefault((LPXENTITY)x_EntityTable, sizeof(x_EntityTable)/sizeof(x_EntityTable[0]) ); //======================================================== // Name : _tcschrs // Desc : same with _tcspbrk // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPTSTR _tcschrs( LPCTSTR psz, LPCTSTR pszchs ) { while( psz && *psz ) { if( _tcschr( pszchs, *psz ) ) return (LPTSTR)psz; psz++; } return NULL; } //======================================================== // Name : _tcsskip // Desc : skip space // Param : // Return : skiped string //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPTSTR _tcsskip( LPCTSTR psz ) { //while( psz && *psz == ' ' && *psz == 13 && *psz == 10 ) psz++; while( psz && isspace(*psz) ) psz++; return (LPTSTR)psz; } //======================================================== // Name : _tcsechr // Desc : similar with _tcschr with escape process // Param : escape - will be escape character // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPTSTR _tcsechr( LPCTSTR psz, int ch, int escape ) { LPTSTR pch = (LPTSTR)psz; while( pch && *pch ) { if( escape != 0 && *pch == escape ) pch++; else if( *pch == ch ) return (LPTSTR)pch; pch++; } return pch; } //======================================================== // Name : _tcselen // Desc : similar with _tcslen with escape process // Param : escape - will be escape character // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== int _tcselen( int escape, LPTSTR srt, LPTSTR end = NULL ) { int len = 0; LPTSTR pch = srt; if( end==NULL ) end = (LPTSTR)sizeof(long); LPTSTR prev_escape = NULL; while( pch && *pch && pch des[i] ) return 1; return -1; } //======================================================== // Name : _tcsenistr // Desc : similar with _tcsistr with escape process // Param : escape - will be escape character // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPTSTR _tcsenistr( LPCTSTR psz, LPCTSTR str, int len, int escape ) { LPTSTR pch = (LPTSTR)psz; LPTSTR prev_escape = NULL; LPTSTR des = (LPTSTR)str; int i = 0; while( pch && *pch ) { if( escape != 0 && *pch == escape && prev_escape == NULL ) prev_escape = pch; else { prev_escape = NULL; if( _tcsenicmp( pch, str, len, escape ) == 0 ) return (LPTSTR)pch; } pch++; } return pch; } //======================================================== // Name : _tcseistr // Desc : similar with _tcsistr with escape process // Param : escape - will be escape character // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPTSTR _tcseistr( LPCTSTR psz, LPCTSTR str, int escape ) { int len = (int) _tcslen(str); return _tcsenistr( psz, str, len, escape ); } //======================================================== // Name : _SetString // Desc : put string of (psz~end) on ps string // Param : trim - will be trim? // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== void _SetString( LPTSTR psz, LPTSTR end, HM::String* ps, bool trim = FALSE, int escape = 0 ) { //trim if( trim ) { while( psz && psz < end && _istspace(*psz) ) psz++; while( (end-1) && psz < (end-1) && _istspace(*(end-1)) ) end--; } int len = (int) (end - psz); if( len <= 0 ) return; if( escape ) { len = _tcselen( escape, psz, end ); LPTSTR pss = ps->GetBufferSetLength( len ); _tcsecpy( pss, escape, psz, end ); ps->ReleaseBuffer(); } else { //varf�r �ka p� str�ngens l�ngd med ett h�r?! LPTSTR pss = ps->GetBufferSetLength( (len + 1) * sizeof(TCHAR)) ; memcpy( pss, psz, len * sizeof(TCHAR) ); ps->ReleaseBuffer(); } } _tagXMLNode::~_tagXMLNode() { Close(); } void _tagXMLNode::Close() { for( unsigned int i = 0 ; i < childs.size(); i ++) { LPXNode p = childs[i]; if( p ) { delete p; childs[i] = NULL; } } childs.clear(); for( unsigned i = 0 ; i < attrs.size(); i ++) { LPXAttr p = attrs[i]; if( p ) { delete p; attrs[i] = NULL; } } attrs.clear(); } // attr1="value1" attr2='value2' attr3=value3 /> // ^- return pointer //======================================================== // Name : LoadAttributes // Desc : loading attribute plain xml text // Param : pszAttrs - xml of attributes // pi = parser information // Return : advanced string pointer. (error return NULL) //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPTSTR _tagXMLNode::LoadAttributes( LPCTSTR pszAttrs , LPPARSEINFO pi /*= &piDefault*/) { LPTSTR xml = (LPTSTR)pszAttrs; while( xml && *xml ) { if( xml = _tcsskip( xml ) ) { // close tag if( *xml == chXMLTagClose || *xml == chXMLTagPre ) // wel-formed tag return xml; // XML Attr Name TCHAR* pEnd = _tcspbrk( xml, _T(" =") ); if( pEnd == NULL ) { // error if( pi->erorr_occur == false ) { pi->erorr_occur = true; pi->error_pointer = xml; pi->error_code = PIE_ATTR_NO_VALUE; pi->error_string.Format(_T("<%s> attribute has error "), name.c_str()); } return NULL; } LPXAttr attr = new XAttr; attr->parent = this; // XML Attr Name _SetString( xml, pEnd, &attr->name ); // add new attribute attrs.push_back( attr ); xml = pEnd; // XML Attr Value if( xml = _tcsskip( xml ) ) { //if( xml = _tcschr( xml, '=' ) ) if( *xml == '=' ) { if( xml = _tcsskip( ++xml ) ) { // if " or ' // or none quote int quote = *xml; if( quote == '"' || quote == '\'' ) pEnd = _tcsechr( ++xml, quote, pi ? pi->escape_value : 0 ); else { //attr= value> // none quote mode //pEnd = _tcsechr( xml, ' ', '\\' ); pEnd = _tcsepbrk( xml, _T(" >"), pi ? pi->escape_value : 0 ); } bool trim = pi->trim_value; TCHAR escape = pi->escape_value; //_SetString( xml, pEnd, &attr->value, trim, pi ? pi->escape_value : 0 ); _SetString( xml, pEnd, &attr->value, trim, escape ); xml = pEnd; // ATTRVALUE if( pi->entity_value && pi->entitys ) attr->value = pi->entitys->Ref2Entity(attr->value); if( quote == '"' || quote == '\'' ) xml++; } } } } } // not wel-formed tag return NULL; } // attr1="value1" attr2='value2' attr3=value3 /> // ^- return pointer //======================================================== // Name : LoadAttributes // Desc : loading attribute plain xml text // Param : pszAttrs - xml of attributes // pszEnd - last string // pi = parser information // Return : advanced string pointer. (error return NULL) //-------------------------------------------------------- // Coder Date Desc // bro 2004-06-14 //======================================================== LPTSTR _tagXMLNode::LoadAttributes( LPCTSTR pszAttrs, LPCTSTR pszEnd, LPPARSEINFO pi /*= &piDefault*/ ) { LPTSTR xml = (LPTSTR)pszAttrs; while( xml && *xml ) { if( xml = _tcsskip( xml ) ) { // close tag if( xml >= pszEnd ) // wel-formed tag return xml; // XML Attr Name TCHAR* pEnd = _tcspbrk( xml, _T(" =") ); if( pEnd == NULL ) { // error if( pi->erorr_occur == false ) { pi->erorr_occur = true; pi->error_pointer = xml; pi->error_code = PIE_ATTR_NO_VALUE; pi->error_string.Format(_T("<%s> attribute has error "), name.c_str()); } return NULL; } LPXAttr attr = new XAttr; attr->parent = this; // XML Attr Name _SetString( xml, pEnd, &attr->name ); // add new attribute attrs.push_back( attr ); xml = pEnd; // XML Attr Value if( xml = _tcsskip( xml ) ) { //if( xml = _tcschr( xml, '=' ) ) if( *xml == '=' ) { if( xml = _tcsskip( ++xml ) ) { // if " or ' // or none quote int quote = *xml; if( quote == '"' || quote == '\'' ) pEnd = _tcsechr( ++xml, quote, pi ? pi->escape_value : 0 ); else { //attr= value> // none quote mode //pEnd = _tcsechr( xml, ' ', '\\' ); pEnd = _tcsepbrk( xml, _T(" >"), pi ? pi->escape_value : 0 ); } bool trim = pi->trim_value; TCHAR escape = pi->escape_value; //_SetString( xml, pEnd, &attr->value, trim, pi ? pi->escape_value : 0 ); _SetString( xml, pEnd, &attr->value, trim, escape ); xml = pEnd; // ATTRVALUE if( pi->entity_value && pi->entitys ) attr->value = pi->entitys->Ref2Entity(attr->value); if( quote == '"' || quote == '\'' ) xml++; } } } } } // not wel-formed tag return NULL; } // // ^- return pointer //======================================================== // Name : LoadProcessingInstrunction // Desc : loading processing instruction // Param : pszXml - PI string // pi - parser information // Return : advanced string pointer. (error return NULL) //-------------------------------------------------------- // Coder Date Desc // bro 2004-06-14 //======================================================== LPTSTR _tagXMLNode::LoadProcessingInstrunction( LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ ) { // find the end of pi LPTSTR end = _tcsenistr( pszXml, szXMLPIClose, sizeof(szXMLPIClose)-1, pi ? pi->escape_value : 0 ); if( end == NULL ) return NULL; // process pi if( doc ) { LPTSTR xml = (LPTSTR)pszXml; LPXNode node = new XNode; node->parent = this; node->doc = doc; node->type = XNODE_PI; xml += sizeof(szXMLPIOpen)-1; TCHAR* pTagEnd = _tcspbrk( xml, _T(" ?>") ); _SetString( xml, pTagEnd, &node->name ); xml = pTagEnd; node->LoadAttributes( xml, end, pi ); doc->childs.push_back( node ); } end += sizeof(szXMLPIClose)-1; return end; } // // ^- return pointer //======================================================== // Name : LoadComment // Desc : loading comment // Param : pszXml - comment string // pi - parser information // Return : advanced string pointer. (error return NULL) //-------------------------------------------------------- // Coder Date Desc // bro 2004-06-14 //======================================================== LPTSTR _tagXMLNode::LoadComment( LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ ) { // find the end of comment LPTSTR end = _tcsenistr( pszXml, szXMLCommentClose, sizeof(szXMLCommentClose)-1, pi ? pi->escape_value : 0 ); if( end == NULL ) return NULL; // process comment LPXNode par = parent; if( parent == NULL && doc ) par = (LPXNode)&doc; if( par ) { LPTSTR xml = (LPTSTR)pszXml; xml += sizeof(szXMLCommentOpen)-1; LPXNode node = new XNode; node->parent = this; node->doc = doc; node->type = XNODE_COMMENT; node->name = _T("#COMMENT"); _SetString( xml, end, &node->value, FALSE ); par->childs.push_back( node ); } end += sizeof(szXMLCommentClose)-1; return end; } // // ^- return pointer //======================================================== // Name : LoadCDATA // Desc : loading CDATA // Param : pszXml - CDATA string // pi - parser information // Return : advanced string pointer. (error return NULL) //-------------------------------------------------------- // Coder Date Desc // bro 2004-06-14 //======================================================== LPTSTR _tagXMLNode::LoadCDATA( LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ ) { // find the end of CDATA LPTSTR end = _tcsenistr( pszXml, szXMLCDATAClose, sizeof(szXMLCDATAClose)-1, pi ? pi->escape_value : 0 ); if( end == NULL ) return NULL; // process CDATA LPXNode par = parent; if( parent == NULL && doc ) par = (LPXNode)&doc; if( par ) { LPTSTR xml = (LPTSTR)pszXml; xml += sizeof(szXMLCDATAOpen)-1; LPXNode node = new XNode; node->parent = this; node->doc = doc; node->type = XNODE_CDATA; node->name = _T("#CDATA"); _SetString( xml, end, &node->value, FALSE ); par->childs.push_back( node ); } end += sizeof(szXMLCDATAClose)-1; return end; } //======================================================== // Name : LoadOtherNodes // Desc : internal function for loading PI/CDATA/Comment // Param : node - current xml node // pbRet - error occur // pszXml - CDATA string // pi - parser information // Return : advanced string pointer. (error return NULL) //-------------------------------------------------------- // Coder Date Desc // bro 2004-06-14 //======================================================== LPTSTR LoadOtherNodes( LPXNode node, bool* pbRet, LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ ) { LPTSTR xml = (LPTSTR)pszXml; bool do_other_type = true; *pbRet = false; while( xml && do_other_type ) { do_other_type = false; xml = _tcsskip( xml ); LPTSTR prev = xml; // is PI( Processing Instruction ) Node? if( _tcsnicmp( xml, szXMLPIOpen, sizeof(szXMLPIOpen)-1 ) == 0 ) { // processing instrunction parse // return pointer is next node of pi xml = node->LoadProcessingInstrunction( xml, pi ); //if( xml == NULL ) // return NULL; // restart xml parse } if( xml != prev ) do_other_type = true; xml = _tcsskip( xml ); prev = xml; // is comment Node? if( _tcsnicmp( xml, szXMLCommentOpen, sizeof(szXMLCommentOpen)-1 ) == 0 ) { // processing comment parse // return pointer is next node of comment xml = node->LoadComment( xml, pi ); // comment node is terminal node if( node->parent && node->parent->type != XNODE_DOC && xml != prev ) { *pbRet = true; return xml; } // restart xml parse when this node is root doc node } if( xml != prev ) do_other_type = true; xml = _tcsskip( xml ); prev = xml; // is CDATA Node? if( _tcsnicmp( xml, szXMLCDATAOpen, sizeof(szXMLCDATAOpen)-1 ) == 0 ) { // processing CDATA parse // return pointer is next node of CDATA xml = node->LoadCDATA( xml, pi ); // CDATA node is terminal node if( node->parent && node->parent->type != XNODE_DOC && xml != prev ) { *pbRet = true; return xml; } // restart xml parse when this node is root doc node } if( xml != prev ) do_other_type = true; } return xml; } // // // or // // ^- return pointer //======================================================== // Name : Load // Desc : load xml plain text // Param : pszXml - plain xml text // pi = parser information // Return : advanced string pointer (error return NULL) //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPTSTR _tagXMLNode::Load( LPCTSTR pszXml, LPPARSEINFO pi /*= &piDefault*/ ) { // Close it Close(); LPTSTR xml = (LPTSTR)pszXml; xml = _tcschr( xml, chXMLTagOpen ); if( xml == NULL ) return NULL; // Close Tag if( *(xml+1) == chXMLTagPre ) // (pi, comment, CDATA etc) bool bRet = false; LPTSTR ret = NULL; ret = LoadOtherNodes( this, &bRet, xml, pi ); if( ret != NULL ) xml = ret; if( bRet ) return xml; // XML Node Tag Name Open xml++; TCHAR* pTagEnd = _tcspbrk( xml, _T(" />\t\r\n") ); _SetString( xml, pTagEnd, &name ); xml = pTagEnd; // Generate XML Attributte List if( xml = LoadAttributes( xml, pi ) ) { // alone tag if( *xml == chXMLTagPre ) { xml++; if( *xml == chXMLTagClose ) // wel-formed tag return ++xml; else { // error: if( pi->erorr_occur == false ) { pi->erorr_occur = true; pi->error_pointer = xml; pi->error_code = PIE_ALONE_NOT_CLOSED; pi->error_string = _T("Element must be closed."); } // not wel-formed tag return NULL; } } else // open/close tag ... // ^- current pointer { // if text value is not exist, then assign value //if( this->value.IsEmpty() || this->value == _T("") ) if( XIsEmptyString( value ) ) { // Text Value TCHAR* pEnd = _tcsechr( ++xml, chXMLTagOpen, pi ? pi->escape_value : 0 ); if( pEnd == NULL ) { if( pi->erorr_occur == false ) { pi->erorr_occur = true; pi->error_pointer = xml; pi->error_code = PIE_NOT_CLOSED; pi->error_string.Format(_T("%s must be closed with "), name.c_str(), name.c_str()); } // error cos not exist CloseTag return NULL; } bool trim = pi->trim_value; TCHAR escape = pi->escape_value; //_SetString( xml, pEnd, &value, trim, pi ? pi->escape_value : 0 ); _SetString( xml, pEnd, &value, trim, escape ); xml = pEnd; // TEXTVALUE reference if( pi->entity_value && pi->entitys ) value = pi->entitys->Ref2Entity(value); } // generate child nodes while( xml && *xml ) { LPXNode node = new XNode; node->parent = this; node->doc = doc; node->type = type; xml = node->Load( xml,pi ); if( node->name.IsEmpty() == FALSE ) { childs.push_back( node ); } else { delete node; } // open/close tag ... // ^- current pointer // CloseTag case if( xml && *xml && *(xml+1) && *xml == chXMLTagOpen && *(xml+1) == chXMLTagPre ) { // xml+=2; // C if( xml = _tcsskip( xml ) ) { HM::String closename; TCHAR* pEnd = _tcspbrk( xml, _T(" >") ); if( pEnd == NULL ) { if( pi->erorr_occur == false ) { pi->erorr_occur = true; pi->error_pointer = xml; pi->error_code = PIE_NOT_CLOSED; pi->error_string.Format(_T("it must be closed with "), name.c_str() ); } // error return NULL; } _SetString( xml, pEnd, &closename ); if( closename == this->name ) { // wel-formed open/close xml = pEnd+1; // return '>' or ' ' after pointer return xml; } else { xml = pEnd+1; // 2004.6.15 - example alone tag // now it can parse with attribute 'force_arse' if( pi->force_parse == false ) { // not welformed open/close if( pi->erorr_occur == false ) { pi->erorr_occur = true; pi->error_pointer = xml; pi->error_code = PIE_NOT_NESTED; pi->error_string.Format(_T("'<%s> ... ' is not wel-formed."), name.c_str(), closename.c_str() ); } return NULL; } } } } else // Alone child Tag Loaded // else �ؾ��ϴ��� ���ƾ��ϴ��� �ǽɰ���. { //if( xml && this->value.IsEmpty() && *xml !=chXMLTagOpen ) if( xml && XIsEmptyString( value ) && *xml !=chXMLTagOpen ) { // Text Value TCHAR* pEnd = _tcsechr( xml, chXMLTagOpen, pi ? pi->escape_value : 0 ); if( pEnd == NULL ) { // error cos not exist CloseTag if( pi->erorr_occur == false ) { pi->erorr_occur = true; pi->error_pointer = xml; pi->error_code = PIE_NOT_CLOSED; pi->error_string.Format(_T("it must be closed with "), name.c_str() ); } return NULL; } bool trim = pi->trim_value; TCHAR escape = pi->escape_value; //_SetString( xml, pEnd, &value, trim, pi ? pi->escape_value : 0 ); _SetString( xml, pEnd, &value, trim, escape ); xml = pEnd; //TEXTVALUE if( pi->entity_value && pi->entitys ) value = pi->entitys->Ref2Entity(value); } } } } } return xml; } // // // // or // // ^- return pointer //======================================================== // Name : Load // Desc : load xml plain text for xml document // Param : pszXml - plain xml text // pi = parser information // Return : advanced string pointer (error return NULL) //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPTSTR _tagXMLDocument::Load( LPCTSTR pszXml, LPPARSEINFO pi /*= NULL*/ ) { LPXNode node = new XNode; node->parent = (LPXNode)this; node->type = XNODE_ELEMENT; node->doc = this; LPTSTR end; if( pi == NULL ) pi = &parse_info; if( (end = node->Load( pszXml, pi )) == NULL ) { delete node; if (pi->erorr_occur == true) { // This error should be logged. HM::String sErrorMessage; sErrorMessage.Format(_T("The XML data stream contains formatting errors. Code: %d, Error: %s"), pi->error_code, pi->error_string.c_str()); HM::ErrorManager::Instance()->ReportError(HM::ErrorManager::Medium, 4229, "_tagXMLDocument::Load", sErrorMessage); } return NULL; } childs.push_back( node ); // Load Other Node after (pi, comment, CDATA etc) LPTSTR ret; bool bRet = false; ret = LoadOtherNodes( node, &bRet, end, pi ); if( ret != NULL ) end = ret; return end; } LPXNode _tagXMLDocument::GetRoot() { auto it = childs.begin(); for( ; it != childs.end() ; ++(it) ) { LPXNode node = *it; if( node->type == XNODE_ELEMENT ) return node; } return NULL; } //======================================================== // Name : GetXML // Desc : convert plain xml text from parsed xml attirbute // Param : // Return : converted plain string //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== HM::String _tagXMLAttr::GetXML( LPDISP_OPT opt /*= &optDefault*/ ) { HM::String sRetVal; sRetVal += name; sRetVal += "="; sRetVal += opt->value_quotation_mark; sRetVal += (opt->reference_value&&opt->entitys?opt->entitys->Entity2Ref(value):value); sRetVal += opt->value_quotation_mark; sRetVal += " "; return sRetVal; } //======================================================== // Name : GetXML // Desc : convert plain xml text from parsed xml node // Param : // Return : converted plain string //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== HM::String _tagXMLNode::GetXML( LPDISP_OPT opt /*= &optDefault*/ ) { HM::String sRetVal; // tab if( opt && opt->newline ) { sRetVal += "\r\n"; for( int i = 0 ; i < opt->tab_base ; i++) sRetVal += '\t'; } if( type == XNODE_DOC ) { for( unsigned int i = 0 ; i < childs.size(); i++ ) sRetVal += childs[i]->GetXML( opt ); return sRetVal; } else if( type == XNODE_PI ) { // GetXML(opt); } //?> sRetVal += szXMLPIClose; return sRetVal; } else if( type == XNODE_COMMENT ) { // <--comment sRetVal +=szXMLCommentOpen; sRetVal += value; //--> sRetVal += szXMLCommentClose; return sRetVal; } else if( type == XNODE_CDATA ) { // <--comment sRetVal += szXMLCDATAOpen; sRetVal += value; //--> sRetVal += szXMLCDATAClose; return sRetVal; } // GetXML(opt); } if( childs.empty() && value.IsEmpty() ) { // alone tag sRetVal += "/>"; } else { // and get child sRetVal += '>'; if( opt && opt->newline && !childs.empty() ) { opt->tab_base++; } for( unsigned int i = 0 ; i < childs.size(); i++ ) sRetVal += childs[i]->GetXML( opt ); // Text Value if( value != _T("") ) { if( opt->newline && !childs.empty() ) { sRetVal += "\r\n"; for( int i = 0 ; i < opt->tab_base ; i++) sRetVal += '\t'; } sRetVal += (opt->reference_value&&opt->entitys?opt->entitys->Entity2Ref(value):value); } // CloseTag if( opt && opt->newline && !childs.empty() ) { sRetVal += "\r\n"; for( int i = 0 ; i < opt->tab_base-1 ; i++) sRetVal += '\t'; } sRetVal += "'; if( opt && opt->newline ) { if( !childs.empty() ) opt->tab_base--; } } return sRetVal; } //======================================================== // �Լ��� : GetText // �� �� : ��� �ϳ��� �ؽ�Ʈ ���ڿ��� ��ȯ // �� �� : // ���ϰ� : ��ȯ�� ���ڿ� //-------------------------------------------------------- // �ۼ��� �ۼ��� �ۼ����� // ����� 2004-06-15 //======================================================== HM::String _tagXMLNode::GetText( LPDISP_OPT opt /*= &optDefault*/ ) { std::ostringstream os; if( type == XNODE_DOC ) { for( unsigned int i = 0 ; i < childs.size(); i++ ) os << (LPCTSTR)childs[i]->GetText( opt ); } else if( type == XNODE_PI ) { // no text } else if( type == XNODE_COMMENT ) { // no text } else if( type == XNODE_CDATA ) { os << (LPCTSTR)value; } else if( type == XNODE_ELEMENT ) { if( childs.empty() && value.IsEmpty() ) { // no text } else { // childs text for( unsigned int i = 0 ; i < childs.size(); i++ ) os << (LPCTSTR)childs[i]->GetText(); // Text Value os << (LPCTSTR)(opt->reference_value&&opt->entitys?opt->entitys->Entity2Ref(value):value); } } return os.str().c_str(); } //======================================================== // Name : GetAttr // Desc : get attribute with attribute name // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXAttr _tagXMLNode::GetAttr( LPCTSTR attrname ) { for( unsigned int i = 0 ; i < attrs.size(); i++ ) { LPXAttr attr = attrs[i]; if( attr ) { if( attr->name == attrname ) return attr; } } return NULL; } //======================================================== // Name : GetAttrs // Desc : find attributes with attribute name, return its list // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== XAttrs _tagXMLNode::GetAttrs( LPCTSTR name ) { XAttrs attrs; for( unsigned int i = 0 ; i < attrs.size(); i++ ) { LPXAttr attr = attrs[i]; if( attr ) { if( attr->name == name ) attrs.push_back( attr ); } } return attrs; } //======================================================== // Name : GetAttrValue // Desc : get attribute with attribute name, return its value // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== HM::String _tagXMLNode::GetAttrValue( LPCTSTR attrname ) { LPXAttr attr = GetAttr( attrname ); return attr ? attr->value : ""; } XNodes _tagXMLNode::GetChilds() { return childs; } //======================================================== // Name : GetChilds // Desc : Find childs with name and return childs list // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== XNodes _tagXMLNode::GetChilds( LPCTSTR name ) { XNodes nodes; for( unsigned int i = 0 ; i < childs.size(); i++ ) { LPXNode node = childs[i]; if( node ) { if( node->name == name ) nodes.push_back( node ); } } return nodes; } //======================================================== // Name : GetChild // Desc : get child node with index // Param : // Return : NULL return if no child. //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXNode _tagXMLNode::GetChild( unsigned int i ) { if( i >= 0 && i < childs.size() ) return childs[i]; return NULL; } //======================================================== // Name : GetChildCount // Desc : get child node count // Param : // Return : 0 return if no child //-------------------------------------------------------- // Coder Date Desc // bro 2002-12-26 //======================================================== int _tagXMLNode::GetChildCount() { return (int) childs.size(); } //======================================================== // Name : GetChild // Desc : Find child with name and return child // Param : // Return : NULL return if no child. //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXNode _tagXMLNode::GetChild( LPCTSTR name ) { for( unsigned int i = 0 ; i < childs.size(); i++ ) { LPXNode node = childs[i]; if( node ) { if( node->name == name ) return node; } } return NULL; } //======================================================== // Name : GetChildValue // Desc : Find child with name and return child's value // Param : // Return : NULL return if no child. //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPCTSTR _tagXMLNode::GetChildValue( LPCTSTR name ) { LPXNode node = GetChild( name ); return (node != NULL)? (LPCTSTR)node->value : NULL; } HM::String _tagXMLNode::GetChildText( LPCTSTR name, LPDISP_OPT opt /*= &optDefault*/ ) { LPXNode node = GetChild( name ); return (node != NULL)? node->GetText(opt) : _T(""); } LPXAttr _tagXMLNode::GetChildAttr( LPCTSTR name, LPCTSTR attrname ) { LPXNode node = GetChild(name); return node ? node->GetAttr(attrname) : NULL; } LPCTSTR _tagXMLNode::GetChildAttrValue( LPCTSTR name, LPCTSTR attrname ) { LPXAttr attr = GetChildAttr( name, attrname ); return attr ? (LPCTSTR)attr->value : NULL; } //======================================================== // Name : Find // Desc : find node with tag name from it's all childs // Param : // Return : NULL return if no found node. //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXNode _tagXMLNode::Find( LPCTSTR name ) { auto it = childs.begin(); for( ; it != childs.end(); ++(it)) { LPXNode child = *it; if( child->name == name ) return child; auto it = child->childs.begin(); for( ; it != child->childs.end(); ++(it)) { LPXNode find = child->Find( name ); if( find != NULL ) return find; } } return NULL; } //======================================================== // Name : GetChildIterator // Desc : get child nodes iterator // Param : // Return : NULL return if no childs. //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== XNodes::iterator _tagXMLNode::GetChildIterator( LPXNode node ) { auto it = childs.begin(); for( ; it != childs.end() ; ++(it) ) { if( *it == node ) return it; } return childs.end(); } //======================================================== // Name : AppendChild // Desc : add node // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXNode _tagXMLNode::AppendChild( LPCTSTR name /*= NULL*/, LPCTSTR value /*= NULL*/ ) { return AppendChild( CreateNode( name, value ) ); } //======================================================== // Name : AppendChild // Desc : add node // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXNode _tagXMLNode::AppendChild( LPXNode node ) { node->parent = this; node->doc = doc; childs.push_back( node ); return node; } //======================================================== // Name : RemoveChild // Desc : detach node and delete object // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== bool _tagXMLNode::RemoveChild( LPXNode node ) { auto it = GetChildIterator( node ); if( it != childs.end()) { delete *it; childs.erase( it ); return true; } return false; } //======================================================== // Name : GetAttr // Desc : get attribute with index in attribute list // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXAttr _tagXMLNode::GetAttr( unsigned int i ) { if( i >= 0 && i < attrs.size() ) return attrs[i]; return NULL; } //======================================================== // Name : GetAttrIterator // Desc : get attribute iterator // Param : // Return : std::vector::iterator //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== XAttrs::iterator _tagXMLNode::GetAttrIterator( LPXAttr attr ) { auto it = attrs.begin(); for( ; it != attrs.end() ; ++(it) ) { if( *it == attr ) return it; } return attrs.end(); } //======================================================== // Name : AppendAttr // Desc : add attribute // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXAttr _tagXMLNode::AppendAttr( LPXAttr attr ) { attr->parent = this; attrs.push_back( attr ); return attr; } //======================================================== // Name : RemoveAttr // Desc : detach attribute and delete object // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== bool _tagXMLNode::RemoveAttr( LPXAttr attr ) { auto it = GetAttrIterator( attr ); if( it != attrs.end()) { delete *it; attrs.erase( it ); return true; } return false; } //======================================================== // Name : CreateNode // Desc : Create node object and return it // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXNode _tagXMLNode::CreateNode( LPCTSTR name /*= NULL*/, LPCTSTR value /*= NULL*/ ) { LPXNode node = new XNode; node->name = name; node->value = value; return node; } //======================================================== // Name : CreateAttr // Desc : create Attribute object and return it // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXAttr _tagXMLNode::CreateAttr( LPCTSTR name /*= NULL*/, LPCTSTR value /*= NULL*/ ) { LPXAttr attr = new XAttr; attr->name = name; attr->value = value; return attr; } //======================================================== // Name : AppendAttr // Desc : add attribute // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXAttr _tagXMLNode::AppendAttr( LPCTSTR name /*= NULL*/, LPCTSTR value /*= NULL*/ ) { return AppendAttr( CreateAttr( name, value ) ); } //======================================================== // Name : DetachChild // Desc : no delete object, just detach in list // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXNode _tagXMLNode::DetachChild( LPXNode node ) { auto it = GetChildIterator( node ); if( it != childs.end()) { childs.erase( it ); return node; } return NULL; } //======================================================== // Name : DetachAttr // Desc : no delete object, just detach in list // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXAttr _tagXMLNode::DetachAttr( LPXAttr attr ) { auto it = GetAttrIterator( attr ); if( it != attrs.end()) { attrs.erase( it ); return attr; } return NULL; } //======================================================== // Name : CopyNode // Desc : copy current level node with own attributes // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== void _tagXMLNode::CopyNode( LPXNode node ) { Close(); doc = node->doc; parent = node->parent; name = node->name; value = node->value; type = node->type; // copy attributes for( unsigned int i = 0 ; i < node->attrs.size(); i++) { LPXAttr attr = node->attrs[i]; if( attr ) AppendAttr( attr->name, attr->value ); } } //======================================================== // Name : CopyBranch_ // Desc : recursive internal copy branch // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== void _tagXMLNode::CopyBranch_( LPXNode node ) { CopyNode( node ); for( unsigned int i = 0 ; i < node->childs.size(); i++) { LPXNode child = node->childs[i]; if( child ) { LPXNode mychild = new XNode; mychild->CopyNode( child ); AppendChild( mychild ); mychild->CopyBranch_( child ); } } } //======================================================== // Name : AppendChildBranch // Desc : add child branch ( deep-copy ) // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== LPXNode _tagXMLNode::AppendChildBranch( LPXNode node ) { LPXNode child = new XNode; child->CopyBranch( node ); return AppendChild( child ); } //======================================================== // Name : CopyBranch // Desc : copy branch ( deep-copy ) // Param : // Return : //-------------------------------------------------------- // Coder Date Desc // bro 2002-10-29 //======================================================== void _tagXMLNode::CopyBranch( LPXNode branch ) { Close(); CopyBranch_( branch ); } tagXMLEntitys_::tagXMLEntitys_( LPXENTITY entities, int count ) { for( int i = 0; i < count; i++) push_back( entities[i] ); } LPXENTITY tagXMLEntitys_::GetEntity( int entity ) { for( unsigned int i = 0 ; i < size(); i ++ ) { if( at(i).entity == entity ) return LPXENTITY(&at(i)); } return NULL; } LPXENTITY tagXMLEntitys_::GetEntity( LPTSTR entity ) { for( unsigned int i = 0 ; i < size(); i ++ ) { LPTSTR ref = (LPTSTR)at(i).ref; LPTSTR ps = entity; while( ref && *ref ) if( *ref++ != *ps++ ) break; if( ref && !*ref ) // found! return LPXENTITY(&at(i)); } return NULL; } int tagXMLEntitys_::GetEntityCount( LPCTSTR str ) { int nCount = 0; LPTSTR ps = (LPTSTR)str; while( ps && *ps ) if( GetEntity( *ps++ ) ) nCount ++; return nCount; } int tagXMLEntitys_::Ref2Entity( LPCTSTR estr, LPTSTR str, int strlen ) { LPTSTR pes = (LPTSTR)estr; LPTSTR ps = str; LPTSTR ps_end = ps+strlen; while( pes && *pes && ps < ps_end ) { LPXENTITY ent = GetEntity( pes ); if( ent ) { // copy entity meanning char *ps = ent->entity; pes += ent->ref_len; } else *ps = *pes++; // default character copy ps++; } *ps = '\0'; // total copied characters return (int) (ps-str); } int tagXMLEntitys_::Entity2Ref( LPCTSTR str, LPTSTR estr, int estrlen ) { LPTSTR ps = (LPTSTR)str; LPTSTR pes = (LPTSTR)estr; LPTSTR pes_end = pes+estrlen; while( ps && *ps && pes < pes_end ) { LPXENTITY ent = GetEntity( *ps ); if( ent ) { // copy entity string LPTSTR ref = (LPTSTR)ent->ref; while( ref && *ref ) *pes++ = *ref++; } else *pes++ = *ps; // default character copy ps++; } *pes = '\0'; // total copied characters return (int) (pes-estr); } HM::String tagXMLEntitys_::Ref2Entity( LPCTSTR estr ) { HM::String es; if( estr ) { int len = (int) _tcslen(estr); LPTSTR esbuf = es.GetBufferSetLength( len +1); if( esbuf ) Ref2Entity( estr, esbuf, len ); es.ReleaseBuffer(); } return es; } HM::String tagXMLEntitys_::Entity2Ref( LPCTSTR str ) { HM::String s; if( str ) { int nEntityCount = GetEntityCount(str); if( nEntityCount == 0 ) return HM::String(str); int len = (int) (_tcslen(str) + nEntityCount*10); LPTSTR sbuf = s.GetBufferSetLength( len + 1 ); if( sbuf ) Entity2Ref( str, sbuf, len ); s.ReleaseBuffer(); } return s; } HM::String XRef2Entity( LPCTSTR estr ) { return entityDefault.Ref2Entity( estr ); } HM::String XEntity2Ref( LPCTSTR str ) { return entityDefault.Entity2Ref( str ); }