| | | | Browse by category |
XPath is a W3C standard that defines using path syntax to access an element in an XML instance document. LEIF supports a subset of the XPath protocol. The XPath feature in LEIF allows access to elements of the XML Binding tree without having to specify the data type of the element. The LEIF::Member class is the mechanism for containing these elements.
Action
Once the XML instance document has been unmarshaled, an instance of the LEIF::Member class is created to contain an element of the tree. Using the get function, child elements of this top element can be pulled into a LEIF::Member vector. The data value of an individual member of this vector can be obtained as a std::string if it is a simple data type or an object of a class for a complex data type.
The following examples use the schemas from the Purchase Order example that is included with the LEIF installation (see examples/xmlbinding/basic in the LEIF installation directory). Figure 1 shows a portion of the XML instance document.
<purchaseOrder orderDate="1999-10-20">
...
<items>
<item partNum="872-AA">
<productName>Lawnmower</productName>
<quantity>1</quantity>
<USPrice>148.95</USPrice>
<comment>Confirm this is electric</comment>
</item>
<item partNum="926-AA">
<productName>Baby Monitor</productName>
<quantity>1</quantity>
<USPrice>39.98</USPrice>
<shipDate>1999-05-21</shipDate>
</item>
</items>
</purchaseOrder>
Figure 1
The XPath is always relative to a particular node (element) in the tree. The XPath to access the <productName> for the first <item> node would be simply: ?productName?. To access the same node from the <purchaseOrder> node the XPath would be: ?items/item[0]/productName?. The index notation, [0] is necessary for the <item> node since <items> can contain many <item> nodes. In this case the index 0 refers to the first item.
Assuming that the XML instance document has been unmarshaled into the po object of the PurchaseOrder class, Figure 2 shows how to create a LEIF::Member container for po.
#include <rw/leif/xmlol/Member.h>
PurchaseOrder po;
LEIF::Member poContainer = LEIF::Member::createTyped(po);
Figure 2
Nodes of Simple Data Type
Figure 3 shows how to access the productName and USPrice values. Note that the values are always expressed as strings.
LEIF::Vector<LEIF::Member> productNameContainer = //1
LEIF::Member::get(poContainer, "items/item[0]/productName"); //2
LEIF::Vector<LEIF::Member> priceContainer =
LEIF::Member::get(poContainer, "items/item[0]/USPrice");
std::string productNameData, priceData; //3
if (productNameContainer.isEmpty() || priceContainer.isEmpty()) { //4
std::cout << "There was no product name or no price." << std::endl;
}
else {
productNameContainer[0] >> productNameData; //5
priceContainer[0] >> priceData;
std::cout<< "ProductName[" << 0 <<"]: " << productNameData
<< " is $" << priceData << std::endl;
}
//1 The returned object will be a vector of LEIF::Members even if there is just one.
//2 Use the get function to access the productName of the first item in the sequence of items.
//3 Because productName and USPrice are simple data types, their values will be strings.
//4 Check if there was actually a value for each node.
//5 The >> operator is used to retrieve the value from the LEIF::Member. Because an item can have only one productName and only one USPrice, there will be only one value in each of the vectors. This value is accessed using the subscript notation [0].
Figure 3
Nodes of Complex Data Type
XPath can be used to retrieve an object of the complex type from the LEIF::Member vector. Figure 4, for example, demonstrates how to access all the items in the purchase order. Notice in the instance document that the <items> node is a sequence of <item> nodes. The static get function returns a vector even though there is only one <items> node in the document. This code converts the LEIF::Member vector to an object of type Items.
LEIF::Vector<LEIF::Member> itemsContainer =
LEIF::Member::get(poContainer, "items"); //1
Items sequenceOfItems;
itemsContainer[0] >> sequenceOfItems; //2
//1 Get the items node from the purchase order node.
//2 Convert the LEIF::Member object to an Items object.
Figure 4
The example in Figure 5, demonstrates how to access each of the <item> nodes in the sequence. In this case the XPath, 'item' is relative to the <items> node rather than the <purchase order> node as in the previous examples.
std::string productNameData;
LEIF::Vector<LEIF::Member> itemContainer = //1
LEIF::Member::get(itemsContainer[0], "item");
for(int i = 0 ; i < (int)itemContainer.length(); i++) //2
{
LEIF::Vector<LEIF::Member> productNameContainer =
LEIF::Member::get(itemContainer[i], "productName");
productNameContainer[0] >> productNameData; //3
std::cout<< "ProductName[" << i <<"]: " << productNameData <<
std::endl;
}
//1 Obtain the vector of all nodes in the Item node.
//2 Iterate through each item in turn.
//3 An item can have only one productName so the subscript [0] will give us this value.
Figure 5
Namespaces
If the schema file has namespace-qualified references, then the XPath must be namespace- qualified. The example in Figure 6, uses the XmlNamespaceStack to access namespace qualified nodes.
LEIF::Member poContainer = LEIF::Member::createTyped(mypo); //1
LEIF::XmlNamespaceStack nsStack;
LEIF::XmlNamespace mynamespace;
mynamespace.setPrefix("po"); //2
mynamespace.setURI("http://www.example.com/PO1"); //3
nsStack.pushScope(); //4
nsStack.addNamespace(mynamespace);
LEIF::Vector<LEIF::Member> productNameContainer = LEIF::Member::get(poContainer, "po:items[0]/po:item[0]/po:productName", nsStack); //5
//1 Create the top level container as in the previous examples.
//2 The namespace prefix should match the namespace used in the schema.
//3 The namespace URI should match the URI specified in the schema for the prefix.
//4 Add the namespace to the stack. Repeat these steps for any additional namespace that will be referenced.
//5 The get method of LEIF::Member is overloaded to take the XmlNamespaceStack as an argument. Use the XPath to access the appropriate node but namespace qualify the nodes.
Figure 6
Complete examples are available to download.
click here to download the namespace example
click here to download the basic example
Reference:
XML Binding Library Reference Guide - LEIF::Member section
W3 Schools - http://www.w3schools.com/XPath/default.asp