Goal: To retrieve the value of any leaf node with one line of code.
Solution:
Wrap the XML Api of choice with the getXValue method. Examples:
// get the value of the name of the first object contained in the second ejb objectName= xmlRoot.getXValue(�ejb�, 2 , �object�, 1, �name�); // get the value of the shortname of the third ejb ejbShortName = xmlRoot.getXValue(�ejb�, 3 , �shortname�); // variation for non OO languages (see JavaScript Implementation below): objectName = getXValue(xmlRoot , �ejb�, 2 , �object�, 1, �name�); // variation for C++ (subclass node, overload bracket operator and String cast) // non-trivial implementation !! I did this 5 year ago, can't remember the details! objectName = xmlRoot (�ejb�, 2)(�object�, 1)(�name�);Assumptions
The XML document only contains text values and only at the leaf nodes.
Comments
This is One based to make comments readable, this can be easily changed to zero based if you must.
Test harness validates XML navigation at devlopment time. No runtime checking to keep code simple (in this implementation).
Based on a design for Semantic Data Objects by OliverSims circa 1995.
JavaScript Implementation (using Flash XML libraries) --PaulCaswell
function getXValue(xRoot) // <a>,1, <b>,2 , .... { // first argument is the XML document // additional arguments are determined at run-time var numArgs = arguments.length; var childNode = xRoot; for (i = 1; i <= numArgs; i++) { var label = arguments[i]; var pos = arguments[++i]; // if no leaf position assume the first if(pos == null) pos = 1; childNode = this.findChildNode(childNode, label, pos); } return childNode.firstChild.nodeValue; } function findChildNode(xRoot, label, pos) { // first argument is the XML Node // additional arguments are label name and position // returns node or null if not found var found = new Boolean("false"); var numfound = 0; var currNode = xRoot.firstChild; do { if (currNode.nodeName == label) { if (++numfound == pos) { found = true; break; } } currNode = currNode.nextSibling; }while (found == false && currNode != null) return currNode; }
I'm putting together something similar to the above, in C++, but with a little twist - the first example above would instead be written as:
std::string result = root.GetValue("ejb[1].object.name");or
std::string result = root.GetValue("ejb[%d].object[%d].name", 1, 0);etc.
-- MikeSmith