CMarkup RestorePos Method

bool CMarkup::RestorePos( MCD_CSTR szPosName = "", int nMap = 0 );

Call RestorePos to return to a position previously saved with the SavePos method. The current position consists of the parent, main and child positions. The RestorePos method returns false if there is no saved position by the name szPosName. When you resume navigating at the restored position, both the main position and the child position will be where they were when they were saved.

Update September 27, 2008: The optional nMap argument is used for additional maps. You can have any number of maps to save and restore positions of different sets of indexing information. The default map is 0. For lookup examples, and more about using multiple maps, see SetMapSize.

SavePos is implemented with a map of name position pairs. This is a quick lookup, but it is not the efficient way to navigate around in CMarkup when you don't need a lookup. You can tell a good lookup scenario when you already have unique ID values for elements in your document.

In the following example, the position of the Total and Data elements are saved with SavePos. While looping through the data values, we switch back and forth between the Total position and the Data position using RestorePos, and the Total is updated as the values are added under Data.

int anSomeData[] = { 10, 30, 50, 20, 90, 0 };
CMarkup xml;
xml.AddElem( _T("SavePosExample") );
xml.IntoElem();
xml.AddElem( _T("Total") );
xml.SavePos( _T("Total") );
xml.AddElem( _T("Data") );
xml.SavePos( _T("Data") );
for ( int nD=0; anSomeData[nD]; ++nD )
{
  xml.RestorePos( _T("Total") );
  xml.SetData( _ttoi(xml.GetData()) + anSomeData[nD] );
  xml.RestorePos( _T("Data") );
  xml.AddChildElem( _T("Value"), anSomeData[nD] );
}

This is the resulting XML document, indented for illustration.

<SavePosExample>
  <Total>200</Total>
  <Data>
    <Value>10</Value>
    <Value>30</Value>
    <Value>50</Value>
    <Value>20</Value>
    <Value>90</Value>
  </Data>
</SavePosExample>

But this is not a lookup scenario, so there is a more efficient way to implement the same set of operations without SavePos and RestorePos. By using known sibling/parent/child relationships, the example above could be re-written as follows.

int anSomeData[] = { 10, 30, 50, 20, 90, 0 };
CMarkup xml;
xml.AddElem( _T("SavePosExample") );
xml.IntoElem();
xml.AddElem( _T("Total") );
xml.AddElem( _T("Data") );
for ( int nD=0; anSomeData[nD]; ++nD )
{
  xml.ResetMainPos();
  xml.FindElem();
  xml.SetData( _ttoi(xml.GetData()) + anSomeData[nD] );
  xml.FindElem();
  xml.AddChildElem( _T("Value"), anSomeData[nD] );
}

It is very efficient to call ResetMainPos and FindElem, because they are simple linked list operations and you avoid the overhead of looking up a stored position and name.

 

comment posted RestorePos and remove element problem

Jonathan White 07-Oct-2004

I believe I've discovered a bug/feature which broke my XML. Basically, if you save a position, remove the element to which the position points and then restore the position, the class now has an invalid m_iPos and starts writing stuff in the wrong place.

Thanks for pointing this out. With CMarkup release 8.0, saved positions are removed when the element or containing element is removed (prior to 8.0 restoring to an invalid position causes bad problems). Now RestorePos can even be used as a way of discovering whether or not the element is still in the document. This is a feature that makes RestorePos effective in scenarios that GotoElemIndex is not.