CMarkup FindElem Method
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.
<TESTDOC> <ITEM>one</ITEM> <ITEM>two</ITEM> </TESTDOC>
xml.ResetPos(); 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.
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
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.
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". 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.ResetPos(); xml.FindElem( "//ITEM" ); // first ITEM xml.FindElem( "//ITEM" ); // second ITEM
This is a handy way of finding all the ITEM elements.
xml.ResetPos(); while ( xml.FindElem("//ITEM") ) DoSomethingWithItem(xml);
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.