bool CMarkup::FindElem( MCD_CSTR szName = NULL );

The FindElem should be thought of as "FindNextElem" because it goes forward from the current main position to the next matching sibling element. If there is no next sibling element it returns false and leaves the main position where it was.

In the following example, if there is no current position (when the document is loaded or after calling ResetPos), calling FindElem() will set the main position to the TESTDOC element. Calling FindElem() a second time will return false and leave the current main position at the TESTDOC element.

xml.FindElem(); // succeeds, at TESTDOC
xml.FindElem(); // fails, stays at TESTDOC

Going into TESTDOC, the first call to FindElem() sets the main position to the first ITEM element. If the main position is at the first ITEM element then calling FindElem() will set the main position to the second ITEM element.

xml.IntoElem(); // inside TESTDOC
xml.FindElem(); // first ITEM
xml.FindElem(); // second ITEM

Having no main position is like being before the first child of the current parent position. This means that the first call to FindElem() will go to the first child of the parent position element. The ResetMainPos method clears the main position.

The FindElem method has an optional argument which allows you to specify a tag name or path. The simplest use of this argument is to pass the tag name. Calling FindElem("ITEM") will only succeed if a sibling ITEM element is found after the main position under the current parent position. If there is no main position, it will look for the first ITEM element under the current parent.

If the main position is at the first ITEM element in the above example, then calling FindElem("ITEM") will set the main position to the second ITEM element. Since there is no THING element, calling FindElem("THING") would not affect the main position and return false.

Update March 24, 2009: FindElem can be used with CMarkup release 11.0 developer version file read mode (see C++ XML reader). Unlike in regular mode, if an element is not found in file read mode then the current position will be at the end tag of the parent element or at the end of the document if the starting position was not within a parent element. In paths, child predicates are not supported.

See Also:

Navigating and Getting Information From a Document
Navigating Levels in CMarkup

CMarkup Developer License

The folowing path features which go beyond a single tag name are only in CMarkup Developer and the free XML editor  FOAL C++ scripting, and are more fully described in Paths In CMarkup.

Specifying a tag name is an example of a relative pathname meaning that it searches for the specified element starting from the current element. You can also use an absolute pathname such as "/TESTDOC/ITEM" to search starting at the root of the document. When a tag name does not need to be compared, use an asterisk as in FindElem("/*/ITEM") which does not check the root element tag name.

xml.FindElem( "/*/ITEM" ); // the first ITEM

Since it is an absolute path starting with a slash, it restarts looking from the top of the document. To go directly to the second ITEM, the path is "/TESTDOC/ITEM[2]". The GetElemPath method provides this absolute path string for the current element.

Even more useful is the "anywhere path" starting with // which causes FindElem to search for the next matching element moving forward in the document (depth first traversal). It does not restart from the beginning of the document, it looks after the current position.

xml.FindElem( "//ITEM" ); // first ITEM
xml.FindElem( "//ITEM" ); // second ITEM

This is a handy way of finding all the ITEM elements.

while ( xml.FindElem("//ITEM") )

CMarkup paths support simple predicates [n] [@attrib] [@a='X'] [CHILDELEM]. See Paths In CMarkup.

Update November 20, 2010: CMarkup release 11.3 introduces document flags to trim whitespace and collapse whitespace (see Whitespace and CMarkup). If one of these flags is set in the document, attribute value predicates in paths will be affected because attribute values from the document will be trimmed or collapsed before being compared to the value specified in the predicate.