コード例 #1
0
ファイル: CTaskFileHelper.cpp プロジェクト: Tomas1/LK8000
bool CTaskFileHelper::SaveTaskRule(XMLNode node) {
    if (!node) {
        return false;
    }

    XMLNode FinishNode = node.AddChild(ToString(_T("finish")), false);
    if (!FinishNode) {
        return false;
    }
    SetAttribute(FinishNode, _T("fai-height"), EnableFAIFinishHeight);
    SetAttribute(FinishNode, _T("min-height"), FinishMinHeight);

    XMLNode StartNode = node.AddChild(ToString(_T("start")), false);
    if (!StartNode) {
        return false;
    }
    SetAttribute(StartNode, _T("max-height"), StartMaxHeight);
    SetAttribute(StartNode, _T("max-height-margin"), StartMaxHeightMargin);
    SetAttribute(StartNode, _T("max-speed"), StartMaxSpeed);
    SetAttribute(StartNode, _T("max-speed-margin"), StartMaxSpeedMargin);
    switch (StartHeightRef) {
        case 0:
            SetAttribute(StartNode, _T("height-ref"), _T("AGL"));
            break;
        case 1:
            SetAttribute(StartNode, _T("height-ref"), _T("ASL"));
            break;
    }
    return true;
}
コード例 #2
0
ファイル: CTaskFileHelper.cpp プロジェクト: Tomas1/LK8000
bool CTaskFileHelper::SaveOption(XMLNode node) {
    if (!node) {
        return false;
    }

    XMLNode OptNode = node.AddChild(ToString(_T("options")), false);
    if (!OptNode) {
        return false;
    }

    switch (AutoAdvance) {
        case 0:
            SetAttribute(OptNode, _T("auto-advance"), _T("Manual"));
            break;
        case 1:
            SetAttribute(OptNode, _T("auto-advance"), _T("Auto"));
            break;
        case 2:
            SetAttribute(OptNode, _T("auto-advance"), _T("Arm"));
            break;
        case 3:
            SetAttribute(OptNode, _T("auto-advance"), _T("ArmStart"));
            break;
        case 4:
            SetAttribute(OptNode, _T("auto-advance"), _T("ArmTPs"));
            break;
    }

    if (AATEnabled && !DoOptimizeRoute()) { // AAT Task
        SetAttribute(node, _T("type"), _T("AAT"));
        if (!SaveOptionAAT(OptNode)) {
            return false;
        }
    } else if (DoOptimizeRoute()) { // Paraglider optimized Task
        SetAttribute(node, _T("type"), _T("Race"));
        if (!SaveOptionRace(OptNode)) {
            return false;
        }
    } else { // default Task
        SetAttribute(node, _T("type"), _T("Default"));
        if (!SaveOptionDefault(OptNode)) {
            return false;
        }
    }

    if (!SaveTaskRule(OptNode.AddChild(ToString(_T("rules")), false))) {
        return false;
    }

    return true;
}
コード例 #3
0
ファイル: CTaskFileHelper.cpp プロジェクト: Tomas1/LK8000
bool CTaskFileHelper::SaveWayPointList(XMLNode node) {
    for (std::set<size_t>::const_iterator it = mWayPointToSave.begin(); it != mWayPointToSave.end(); ++it) {
        if (!SaveWayPoint(node.AddChild(ToString(_T("point")), false), WayPointList[*it])) {
            return false;
        }
    }
    return true;
}
コード例 #4
0
ファイル: CTaskFileHelper.cpp プロジェクト: Tomas1/LK8000
bool CTaskFileHelper::SaveOptionRace(XMLNode node) {
    if (!node) {
        return false;
    }
    if (PGNumberOfGates > 0) {
        if (!SaveTimeGate(node.AddChild(ToString(_T("time-gate")), false))) {
            return false;
        }
    }

    return true;
}
コード例 #5
0
	void XMLDocument::ParseNodeTree(XMLNode &parentNode, rapidxml::xml_node<> *rapidxmlNode)
	{
		while(rapidxmlNode) {
			XMLNode node(rapidxmlNode->name(), rapidxmlNode->value());

			rapidxml::xml_attribute<> *attr = rapidxmlNode->first_attribute(0);
			while(attr) {
				node.SetAttribute(std::string(attr->name()), std::string(attr->value()));

				attr = attr->next_attribute();
			}

			this->ParseNodeTree(node, rapidxmlNode->first_node(0));

			parentNode.AddChild(node);

			rapidxmlNode = rapidxmlNode->next_sibling();
		}
	}
コード例 #6
0
ファイル: CTaskFileHelper.cpp プロジェクト: Tomas1/LK8000
bool CTaskFileHelper::SaveStartPointList(XMLNode node) {
    if (!node) {
        return false;
    }
    for (unsigned long i = 0; ValidStartPoint(i); ++i) {
        XMLNode PointNode = node.AddChild(ToString(_T("point")), false);
        if (!PointNode) {
            return false;
        }

        SetAttribute(PointNode, _T("idx"), i);

        RenameIfVirtual(i); // TODO: check code is unique ?

        if (!SaveStartPoint(PointNode, StartPoints[i])) {
            return false;
        }
    }
    return true;
}
コード例 #7
0
ファイル: TestRegistry.cpp プロジェクト: Nuos/codeproject
LPVOID	TVTCreateXMLPacket4FinalizeSession(
	TCHAR*	sessionName,
		int	failureCount,
		int	summaryCount,
		int	numberOfTests,
		int	numberOfSuccessfulTests,
		int	numberOfUnsuccessfulTests)
{
	TCHAR*	result	= null,
		templatePath[MAX_PATH],
			tempText[MAX_PATH]	
	;
	if (!GetTemplateActionPath(templatePath)
	)	return	result
	;
//	This open and parse the XML file:  
	XMLNode	xRootNode	= XMLNode::openFileHelper(templatePath,"easyTest");
	XMLNode	xAction		= xRootNode.getChildNode("Action");
	XMLAttribute*	xAttribute	= xAction.AddAttribute(stringDup("command",0),stringDup("updateObject",	0));
	XMLNode	xAttributes	= xAction.getChildNode("Attributes");
	xAttribute	= xAttributes.AddAttribute(stringDup("object",	0),stringDup("session",		0));
	xAttribute	= xAttributes.AddAttribute(stringDup("session",	0),stringDup(sessionName,	0));
	
	XMLNode	xEntity	= xAction.AddChild(stringDup("Entity"),0);

//	Line 'Conclusion'
	XMLNode	xLine	= TVTAddXMLLine(xEntity);
	TVTAddXMLToken(xLine,"Conclusion: ");
	TVTAddXMLToken(xLine,itoa(summaryCount,tempText,10));
	TVTAddXMLToken(xLine," checks were made. There were ");
	TVTAddXMLToken(xLine,itoa(failureCount,tempText,10));
	TVTAddXMLToken(xLine," failures.");
	
//	Line 'Statistics'
	xLine	= TVTAddXMLLine(xEntity);
	TVTAddXMLToken(xLine,"Statistics:");
//	Line # tests are executes.
	xLine	= TVTAddXMLLine(xEntity);
	TVTAddXMLToken(xLine,itoa(numberOfTests,tempText,10));
	if (numberOfTests == 1)
		TVTAddXMLToken(xLine," test is executed.");
	else
		TVTAddXMLToken(xLine," tests are executed.")
	;
	xLine	= TVTAddXMLLine(xEntity);
	if (!numberOfUnsuccessfulTests)
	{
			TVTAddXMLToken(xLine,"No errors detected.");
	}
	else
	{
			TVTAddXMLToken(xLine,itoa(numberOfSuccessfulTests,tempText,10));
			if (numberOfSuccessfulTests == 1)
				TVTAddXMLToken(xLine," test is completed successfully. ");
			else
				TVTAddXMLToken(xLine," tests are completed successfully. ")
			;
		xLine	= TVTAddXMLLine(xEntity);
			TVTAddXMLToken(xLine,itoa(numberOfUnsuccessfulTests,tempText,10));
			if (numberOfUnsuccessfulTests == 1)
				TVTAddXMLToken(xLine," test failed.");
			else
				TVTAddXMLToken(xLine," tests failed.")
			;
	}

//	Line
	int		size;
	LPTSTR	pText	= xRootNode.createXMLString(1,&size);
	result	= new TCHAR [size+1];
	if (result)
	{
		_tcscpy(result,pText);
	}
	free(pText);
	return	result;
}
コード例 #8
0
ファイル: Parser.cpp プロジェクト: Advi42/XCSoar
/**
 * Recursively parse an XML element.
 */
static bool
XML::ParseXMLElement(XMLNode &node, Parser *pXML)
{
  bool is_declaration;
  const TCHAR *text = nullptr;
  XMLNode *pNew;
  enum Status status; // inside or outside a tag
  enum Attrib attrib = eAttribName;

  /* the name of the attribute that is currently being */
  tstring attribute_name;

  assert(pXML);

  // If this is the first call to the function
  if (pXML->nFirst) {
    // Assume we are outside of a tag definition
    pXML->nFirst = false;
    status = eOutsideTag;
  } else {
    // If this is not the first call then we should only be called when inside a tag.
    status = eInsideTag;
  }

  // Iterate through the tokens in the document
  while (true) {
    // Obtain the next token
    NextToken token = GetNextToken(pXML);
    if (gcc_unlikely(token.type == eTokenError))
      return false;

    // Check the current status
    switch (status) {
      // If we are outside of a tag definition
    case eOutsideTag:

      // Check what type of token we obtained
      switch (token.type) {
        // If we have found text or quoted text
      case eTokenText:
      case eTokenQuotedText:
      case eTokenEquals:
        if (text == nullptr)
          text = token.pStr;

        break;

        // If we found a start tag '<' and declarations '<?'
      case eTokenTagStart:
      case eTokenDeclaration:
        // Cache whether this new element is a declaration or not
        is_declaration = token.type == eTokenDeclaration;

        // If we have node text then add this to the element
        if (text != nullptr) {
          size_t length = StripRight(text, token.pStr - text);
          node.AddText(text, length);
          text = nullptr;
        }

        // Find the name of the tag
        token = GetNextToken(pXML);

        // Return an error if we couldn't obtain the next token or
        // it wasnt text
        if (token.type != eTokenText) {
          pXML->error = eXMLErrorMissingTagName;
          return false;
        }

        // If the name of the new element differs from the name of
        // the current element we need to add the new element to
        // the current one and recurse
        pNew = &node.AddChild(token.pStr, token.length,
                              is_declaration);

        while (true) {
          // Callself to process the new node.  If we return
          // FALSE this means we dont have any more
          // processing to do...

          if (!ParseXMLElement(*pNew, pXML)) {
            return false;
          } else {
            // If the call to recurse this function
            // evented in a end tag specified in XML then
            // we need to unwind the calls to this
            // function until we find the appropriate node
            // (the element name and end tag name must
            // match)
            if (pXML->cbEndTag) {
              // If we are back at the root node then we
              // have an unmatched end tag
              if (node.GetName() == nullptr) {
                pXML->error = eXMLErrorUnmatchedEndTag;
                return false;
              }

              // If the end tag matches the name of this
              // element then we only need to unwind
              // once more...

              if (CompareTagName(node.GetName(), pXML->lpEndTag)) {
                pXML->cbEndTag = 0;
              }

              return true;
            } else {
              // If we didn't have a new element to create
              break;
            }
          }
        }
        break;

        // If we found an end tag
      case eTokenTagEnd:

        // If we have node text then add this to the element
        if (text != nullptr) {
          size_t length = StripRight(text, token.pStr - text);
          TCHAR *text2 = FromXMLString(text, length);
          if (text2 == nullptr) {
            pXML->error = eXMLErrorUnexpectedToken;
            return false;
          }

          node.AddText(text2);
          free(text2);
          text = nullptr;
        }

        // Find the name of the end tag
        token = GetNextToken(pXML);

        // The end tag should be text
        if (token.type != eTokenText) {
          pXML->error = eXMLErrorMissingEndTagName;
          return false;
        }

        // After the end tag we should find a closing tag
        if (GetNextToken(pXML).type != eTokenCloseTag) {
          pXML->error = eXMLErrorMissingEndTagName;
          return false;
        }

        // We need to return to the previous caller.  If the name
        // of the tag cannot be found we need to keep returning to
        // caller until we find a match
        if (!CompareTagName(node.GetName(), token.pStr)) {
          pXML->lpEndTag = token.pStr;
          pXML->cbEndTag = token.length;
        }

        // Return to the caller
        return true;

        // Errors...
      case eTokenCloseTag: /* '>'         */
      case eTokenShortHandClose: /* '/>'        */
        pXML->error = eXMLErrorUnexpectedToken;
        return false;
      default:
        break;
      }
      break;

      // If we are inside a tag definition we need to search for attributes
    case eInsideTag:
      // Check what part of the attribute (name, equals, value) we
      // are looking for.
      switch (attrib) {
        // If we are looking for a new attribute
      case eAttribName:
        // Check what the current token type is
        switch (token.type) {
          // If the current type is text...
          // Eg.  'attribute'
        case eTokenText:
          // Cache the token then indicate that we are next to
          // look for the equals
          attribute_name.assign(token.pStr, token.length);
          attrib = eAttribEquals;
          break;

          // If we found a closing tag...
          // Eg.  '>'
        case eTokenCloseTag:
          // We are now outside the tag
          status = eOutsideTag;
          break;

          // If we found a short hand '/>' closing tag then we can
          // return to the caller
        case eTokenShortHandClose:
          return true;

          // Errors...
        case eTokenQuotedText: /* '"SomeText"'   */
        case eTokenTagStart: /* '<'            */
        case eTokenTagEnd: /* '</'           */
        case eTokenEquals: /* '='            */
        case eTokenDeclaration: /* '<?'           */
          pXML->error = eXMLErrorUnexpectedToken;
          return false;
        default:
          break;
        }
        break;

        // If we are looking for an equals
      case eAttribEquals:
        // Check what the current token type is
        switch (token.type) {
          // If the current type is text...
          // Eg.  'Attribute AnotherAttribute'
        case eTokenText:
          // Add the unvalued attribute to the list
          node.AddAttribute(std::move(attribute_name), _T(""), 0);
          // Cache the token then indicate.  We are next to
          // look for the equals attribute
          attribute_name.assign(token.pStr, token.length);
          break;

          // If we found a closing tag 'Attribute >' or a short hand
          // closing tag 'Attribute />'
        case eTokenShortHandClose:
        case eTokenCloseTag:
          assert(!attribute_name.empty());

          // If we are a declaration element '<?' then we need
          // to remove extra closing '?' if it exists
          if (node.IsDeclaration() && attribute_name.back() == _T('?')) {
            attribute_name.pop_back();
          }

          if (!attribute_name.empty())
            // Add the unvalued attribute to the list
            node.AddAttribute(std::move(attribute_name), _T(""), 0);

          // If this is the end of the tag then return to the caller
          if (token.type == eTokenShortHandClose)
            return true;

          // We are now outside the tag
          status = eOutsideTag;
          break;

          // If we found the equals token...
          // Eg.  'Attribute ='
        case eTokenEquals:
          // Indicate that we next need to search for the value
          // for the attribute
          attrib = eAttribValue;
          break;

          // Errors...
        case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/
        case eTokenTagStart: /* 'Attribute <'            */
        case eTokenTagEnd: /* 'Attribute </'           */
        case eTokenDeclaration: /* 'Attribute <?'           */
          pXML->error = eXMLErrorUnexpectedToken;
          return false;
        default:
          break;
        }
        break;

        // If we are looking for an attribute value
      case eAttribValue:
        // Check what the current token type is
        switch (token.type) {
          // If the current type is text or quoted text...
          // Eg.  'Attribute = "Value"' or 'Attribute = Value' or
          // 'Attribute = 'Value''.
        case eTokenText:
        case eTokenQuotedText:
          // If we are a declaration element '<?' then we need
          // to remove extra closing '?' if it exists
          if (node.IsDeclaration() && (token.pStr[token.length - 1]) == _T('?')) {
            token.length--;
          }

          // Add the valued attribute to the list
          if (token.type == eTokenQuotedText) {
            token.pStr++;
            token.length -= 2;
          }

          assert(!attribute_name.empty());

          {
            TCHAR *value = FromXMLString(token.pStr, token.length);
            if (value == nullptr) {
              pXML->error = eXMLErrorUnexpectedToken;
              return false;
            }

            node.AddAttribute(std::move(attribute_name),
                              value, _tcslen(value));
            free(value);
          }

          // Indicate we are searching for a new attribute
          attrib = eAttribName;
          break;

          // Errors...
        case eTokenTagStart: /* 'Attr = <'          */
        case eTokenTagEnd: /* 'Attr = </'         */
        case eTokenCloseTag: /* 'Attr = >'          */
        case eTokenShortHandClose: /* "Attr = />"         */
        case eTokenEquals: /* 'Attr = ='          */
        case eTokenDeclaration: /* 'Attr = <?'         */
          pXML->error = eXMLErrorUnexpectedToken;
          return false;
        default:
          break;
        }
      }
    }
  }
}
コード例 #9
0
ファイル: XMLParser.cpp プロジェクト: krbod/XMLParser
XMLNode* XMLParser::_Parse(wchar_t* buf)
{
	std::wstring token;
	eCurState state = NONE;

	attrMap	   attributeMap;
	std::wstring attrKey;

	XMLNode* curNode = new XMLNode;
	while( _mParsingIndex < _mBufSize )
	{
		switch( buf[_mParsingIndex] )
		{
		case L'<':
			if( state == ELEMENT )				// After element, It could be either closing node or new child node
			{
				if( _IsTokenTab(token) )			// At first, delete the all gap (similar to trim function)
				{
					token.clear();
				}

				if( buf[_mParsingIndex+1] == L'/' )	// In case of closing the node
				{
					curNode->SetElement( token );
					token.clear();

					state = CLOSING_NODE;
					++_mParsingIndex;
				}
				else													// In case of new child node
				{
					curNode->AddChild( _Parse(buf) );
				}
			}
			else														// In case of new node
			{
				++_mParsingIndex;

				if( buf[_mParsingIndex] == L'?' || buf[_mParsingIndex] == L'!')		// if new node is about xml information
				{
					_GetTokenWith(buf, L'>');
				}
				else													// Read the new node's name
				{
					token += buf[_mParsingIndex];
					state = OPENING_NODE;
				}
			}

			break;

		case L'>':
			switch( state )
			{
			case ATTR_VALUE:			// In case that new node's attr setting is all set
				curNode->SetAttrMap(attributeMap);
				attributeMap.clear();

				state = ELEMENT;
				break;

			case CLOSING_NODE:		// In case that making node is all set

				if( curNode->GetName().compare(token) != 0  )
				{
					delete curNode;

					wprintf(L"XML ERROR ( closing element's name isn't correct [%s] ) - line %d", curNode->GetName().c_str(), _mLine );
					return nullptr;
				}

				return curNode;

			case OPENING_NODE:		// In case that new node's name setting is all set
				curNode->SetName( token );
				token.clear();

				state = ELEMENT;
				break;

			default:
				std::wcerr<<L"SWITCH_DEFAULT : "<<__FILE__<<L" "<<__LINE__<<std::endl;
				return nullptr;
			}
			break;

		case L' ':
			switch( state )
			{
			case OPENING_NODE:		// After setting the name of new node
				curNode->SetName( token );
				token.clear();

				state = ATTR_VALUE;
				break;

			case ELEMENT	:				// if ' ' is used for element, then just use that
				token += L' ';
				break;

			default:
				std::wcerr<<L"SWITCH_DEFAULT : "<<__FILE__<<L" "<<__LINE__<<std::endl;
				return nullptr;
			}

			break;

		case L'=':
			switch( state )
			{
			case ELEMENT:					// If '=' is used for element, then just use that
				token += L'=';
				break;

			case ATTR_VALUE:			// In case of setting the attribute, attribute's key will come next
				attrKey = token;
				token.clear();

				state = ATTR_KEY;
				break;

			default:
				std::wcerr<<L"SWITCH_DEFAULT : "<<__FILE__<<L" "<<__LINE__<<std::endl;
				return nullptr;
			}
			break;

		case L'\"':
			switch( state )
			{
			case ATTR_KEY:				// Set the attribute's key
				++_mParsingIndex;

				token = _GetTokenWith(buf, L'\"');
				attributeMap[attrKey] = token;

				attrKey.clear();
				token.clear();

				state = ATTR_VALUE;
				break;

			default:
				std::wcerr<<L"SWITCH_DEFAULT : "<<__FILE__<<L" "<<__LINE__<<std::endl;
				return nullptr;
			}
			break;

		case L'/':								// If node is closed by using '/>'
			if( state == ATTR_VALUE && buf[_mParsingIndex+1] == L'>' )
			{
				curNode->SetAttrMap(attributeMap);
				attributeMap.clear();

				++_mParsingIndex;
				return curNode;
			}
			break;

		default:
			if( buf[_mParsingIndex] == L'\n' )
				++_mLine;
			else
				token += buf[_mParsingIndex];

			break;

		}

		++_mParsingIndex;
	}

	return nullptr;
}
コード例 #10
0
ファイル: CTaskFileHelper.cpp プロジェクト: Tomas1/LK8000
bool CTaskFileHelper::SaveOptionDefault(XMLNode node) {
    if (!node) {
        return false;
    }

    XMLNode nodeStart = node.AddChild(ToString(_T("start")), false);
    if (nodeStart) {
        switch (StartLine) {
            case 0: //circle
                SetAttribute(nodeStart, _T("type"), _T("circle"));
                break;
            case 1: //line
                SetAttribute(nodeStart, _T("type"), _T("line"));
                break;
            case 2: //sector
                SetAttribute(nodeStart, _T("type"), _T("sector"));
                break;
        }
        SetAttribute(nodeStart, _T("radius"), StartRadius);
    } else {
        return false;
    }

    XMLNode nodeFinish = node.AddChild(ToString(_T("finish")), false);
    if (nodeFinish) {
        switch (FinishLine) {
            case 0: //circle
                SetAttribute(nodeFinish, _T("type"), _T("circle"));
                break;
            case 1: //line
                SetAttribute(nodeFinish, _T("type"), _T("line"));
                break;
            case 2: //sector
                SetAttribute(nodeFinish, _T("type"), _T("sector"));
                break;
        }
        SetAttribute(nodeFinish, _T("Radius"), FinishRadius);
    } else {
        return false;
    }

    XMLNode nodeSector = node.AddChild(ToString(_T("sector")), false);
    if (nodeSector) {
        switch (SectorType) {
            case 0: //circle
                SetAttribute(nodeSector, _T("type"), _T("circle"));
                SetAttribute(nodeSector, _T("Radius"), SectorRadius);
                break;
            case 1: //sector
                SetAttribute(nodeSector, _T("type"), _T("sector"));
                SetAttribute(nodeSector, _T("Radius"), SectorRadius);
                break;
            case 2: //DAe
                SetAttribute(nodeSector, _T("type"), _T("DAe"));
                break;
        }
    } else {
        return false;
    }

    return true;
}
コード例 #11
0
ファイル: CTaskFileHelper.cpp プロジェクト: Tomas1/LK8000
bool CTaskFileHelper::Save(const TCHAR* szFileName) {
    if (!WayPointList) return false; // this should never happen, but just to be safe...

    CScopeLock LockTask(LockTaskData, UnlockTaskData);
    StartupStore(_T(". SaveTask : saving <%s>%s"), szFileName, NEWLINE);

    ///////////////////////////////////////////////////////////////
    // TODO : this code is temporary before rewriting task system
    if (AATEnabled || DoOptimizeRoute()) {
        for (unsigned i = 0; ValidTaskPoint(i); ++i) {
            int type = -1;
            if (i == 0) { // Start
                Task[0].AATCircleRadius = StartRadius;
                Task[0].AATSectorRadius = StartRadius;
                Task[0].OutCircle = !PGStartOut;
                type = StartLine;
            } else if (!ValidTaskPoint(i + 1)) { //Finish
                Task[i].AATCircleRadius = FinishRadius;
                Task[i].AATSectorRadius = FinishRadius;
                type = FinishLine;
            }
            if (type != -1) {
                switch (type) {
                    case 0: //circle
                        Task[i].AATType = CIRCLE;
                        break;
                    case 1: //line
                        Task[i].AATType = LINE;
                        break;
                    case 2: //sector
                        Task[i].AATType = SECTOR;
                        break;
                }
            }
        }
    }
    ///////////////////////////////////////////////////////////////


    XMLNode topNode = XMLNode::createXMLTopNode();
    XMLNode rootNode = topNode.AddChild(ToString(_T("lk-task")), false);

    if (!SaveOption(rootNode)) {
        return false;
    }

    if (!SaveTaskPointList(rootNode.AddChild(ToString(_T("taskpoints")), false))) {
        return false;
    }
    if (EnableMultipleStartPoints && ValidStartPoint(0)) {
        if (!SaveStartPointList(rootNode.AddChild(ToString(_T("startpoints")), false))) {
            return false;
        }
    }
    if (!SaveWayPointList(rootNode.AddChild(ToString(_T("waypoints")), false))) {
        return false;
    }

    int ContentSize = 0;
    LPCTSTR szContent = topNode.createXMLString(1, &ContentSize);
    Utf8File file;
    if (!file.Open(szFileName, Utf8File::io_create)) {
        return false;
    }

    file.WriteLn(szContent);
    file.Close();

    return true;
}