Use DataseTnavigator to make XPath queries on the data set
Release Date: 9/21/2004
| Update Date: 9/21/2004
ARPAN DESAI
Microsoft Corporation
August 2004
Applicable to:
Xml
DataSetnavigator
Summary: ARPAN DESAI discusses DataSetNavigator, which provides powerful features and flexibility in XML programming model while avoiding overhead of converting the entire DataSet into XmlDATADOCUMENT objects.
Click here to download the code example of this article.
This page
Introduction to build XPath NavigatorDataSetnavigator Details Summary on Data Set
Introduction
For a while, DARE has always asked me to write an article for MSDN. Since Microsoft Visual Studio 2005 Beta 1 has been released, I took the time to write some ideas I have for this time: Xpathnavigator on DataSet.
XMLDATADOCUMENT initially appeared as a component, which allows the user to have an editable hierarchy of Microsoft ADO.NET DataSet data. The main use case is the function of executing the XSLT conversion on the DataSet to generate HTMLs used to represent on the web page. Unfortunately, the performance of XMLDATADOCUMENT is usually a bottleneck during the XSLT process.
One solution to this problem is to use the WriteXML () method on the DataSet and load serialized content into the XMLDocument or XPathDocument class. Although this method uses this method to significantly improve performance, it is still not optimal due to serialization and re-analyzing XML data. In addition, data to be converted or queried is now residing in DataSet and XMLDocument / XPathDocument, which means greatly increasing memory usage. The ideal solution should have the performance of this XML storage area (such as xpathDocument, while occupying the smallest memory overhead.
This article describes the implementation of a class named DataSetNavigator, which is trying to solve this problem in an ideal way.
Back to top
Build XPath Navigator on the data set
Xpathnavigator is a read-only cursor on the XML data source. The XML cursor is like a lens on an XML node each time, but is different from the push-based API (such as XmlReader), the cursor can be placed anywhere in an XML document any given time. Xpathnavigator is an excellent alternative for implementing an XML interface on non-XML data because it allows XML views of the data source in real time without having to convert the entire data source into XML tree.
By proper implementation, you can use it to query file systems, Windows registry, Active Directory storage, or any other type of hierarchical data store. In the previous article, Steve Saxon used ObjectXPathnavigator created an XPathnavigator on the object chart on the object chart.
The XSLTransform class in Microsoft .NET Framework uses XPathnavigator to perform XSLT processing on these sources. In addition, the XPathnavigator API also enables XPath queries. By implementing DataSetnavigator, we can perform XSLT conversion and XPath queries on the DataSet content.
One must be proposed is: Why is the implementation of DataSetNavigator than XmlDATADOCUMENT? XMLDATADOCUMENT has a root cause of performance issues that it has editable capabilities. Whenever change occurs in an instance of XMLDATADECUMENT, the change is propagated to the DataSet associated with it. Instead, any changes made to DataSet also synchronize XMLDATADECUMENT. Even if there is no change, the overhead of this will prevent the optimal performance during the query or conversion process. In both scenarios, you don't need to edit; so we can create more efficient XPathnavigator implementations by ignoring overhead of synchronization. Back to top
Detailed information for DataSetnavigator
The goal is quite simple to complete the fast, lightweight XPathnavigator implementation at the top of the DataSet. The most complex feature to be implemented is to understand the nested relationship in DataSet, which can represent hierarchies by means of DataSetnavigator.
The first step in achieving DataSetnavigator is to understand how to model the basic data source using XPathnavigator. When providing the XML architecture for DataSet, the rules used to generate XML are quite simple from the XMLDATADOCUMENT and WRITEXML () methods.
• The name of the DataSet is the root element in XML. • Not a row in any table of nesting relationships, all of the child elements of the root element. • The column of the table is the child elements in each row element. • If there is any nesting line, these rows are also sub-elements of the row element.
Conceptually, DataSetnavigator is implemented by two main parts. The first part is the ability to generate simple trees based on DataSet. The second part is the ability to navigate the tree by realizing Xpathnavigator. In the implementation provided, the tree will generate trees when the user instantiate DataSetnavigator, which will lead to more overhead in advance to create DataSetNavigator, but in the actual use process will be much lower.
The tree is built from a series of nodes, all of which are derived from the DataSetNode class. Abstract DataSetNode classes have basic navigation that requires traversal spanning trees, and has several very important members:
• Parent - Parent member points to the parent DataSetNode of the current node. • Children - Sub membership is the array of DataSetNodes, which represents the child node of the current node. • SIBLingPosition - SiblingPosition member represents zero-based index relative to the current node location of the same level. This is required, so the movement between the same level can be achieved more easily. • LocalName - localname points to atomic strings, which are the local name of the current node. Xpathnavigators uses XMLNameTable to initiate and disclose the namespace URL of the local name, named space prefix, and a given document. This takes into account the comparison of low overhead objects that occur when searching for these items, rather than high overhead strings.
Our actual trees are built from special classes and these classes are derived from DataSetNode. These special classes correspond to DataSetnavigator from different types of locations from DataSet. Based on the above XML serialization rules, we can have three types of interest:
• TopNode - This is a top-level element node that is disclosed on the XPathnavigator on DataSet. • TABLEROWNODE - This element node is located on a separate line in DataSet. • ColumnRownode - This element node is located on a particular column, a specific row. These three node types cover different locations available in data sets. There are also two other DataSetNode derived types, which do not represent the location in the DataSet, but it is necessary to complete the DataSetnavigator.
• RootNode - Each document has the root; this node is an extremely simple node type, which represents the root of the document. • CellValuenode - We need a way to represent actual data in DataSet. Each columnRownode in the tree has a single CellValuEnode child node that includes the data. Note that CellValuEnode's implementation does not cause copying of data already located in the DataSet, but returns a DataSet instance.
Back to top
usage
The use of DataSetnavigator is similar to any other XPathnavigator. DataSetNavigator can be passed to the XSLTransform class to perform XSLT processing, as shown in the example below:
Dataset mydataset = new dataset ();
...
DataSetnavigator Mynavigator = New DataSetnavigator (MyDataSet);
Xsltransform myTransform = new xsltransform ();
MyTransform.Load ("Transform.xsl");
MyTransform.Transform (MyNavigator, Null, Console.out);
In addition, XPath queries can be performed for DataSet, as shown in the example below:
Using system;
Using system.data;
USING SYSTEM.XML;
Using system.xml.xpath;
USING Microsoft.xml;
Public class datasetnavtest {
Public static dataset createDataSet () {
DataSet Custds = New Dataset ("Books");
DataTable ORDERSTABLE = Custds.Tables.Add ("Book");
Datacolumn Pkcol = ORDERSTABLE.COLUMNS.ADD ("BookID", TypeOf (int32));
ORDERSTABLE.COLUMNS.ADD ("Title", TypeOf (String));
ORDERSTABLE.COLUMNS.ADD ("Quantity", TypeOf (int));
ORDERSTABLE.COLUMNS.ADD ("Unitprice", TypeOf (Decimal);
ORDERSTABLE.COLUMNS.ADD ("Category", TypeOf (String);
ORDERSTABLE.PRIMARYKEY = New Datacolumn [] {pkcol};
ORDERSTABLE.ROWS.ADD (New Object [] {101,
"Quantum Physics for Beginners", 2, 50, "Science"}; ORDERSTABLE.ROWS.AD (New Object [] {201,
"Repair Your Car with Twine", 100, 24.99, "Automotive"});
ORDERSTABLE.ROWS.ADD (New Object [] {301,
"The Secret of Life, The Universe and Everything", 42, 41.99, "Humor"});
Custds.acceptchanges ();
Return Custds;
}
Public static void main (String [] args) {
DataSet DS = CreateDataSet ();
Console.writeline (DS.GETXML ());
DataSetnavigator NAV = New DataSetnavigator (DS);
XpathNodeTeiterator it =
Nav.select ("/ Books / Book [(Unitprice * Quantity)> 1000]");
While (item.movenext ()) {
/ * Print Title and total price of order using xpath queries * /
String itemtotal =
iTer.current.evaluate ("Unitprice * Quantity"). TOSTRING ();
String itemtitle =
iTer.current.evaluate ("String (Title)). TOSTRING ();
Console.writeline (" {0} = {1}", itemtitle, itemtotal;
/ * Print Title and Total Price of Order Using DataSet APIS * /
DataSetnavigator Nav2 = (DataSetnavigator) ore.current.clone ();
DataRow Row = Nav2.GetDataRow ();
String itemtotal2 =
((DECIMAL) ROW ["Unitprice"]) * ((int) Row ["Quantity"]). TOSTRING ();
String itemtitle2 = row ["title"]. TOSTRING ();
Console.writeline ("- {0} = {1}", itemtitle2, itemtotal2);
}
}
}
In addition to the XPathnavigator, DataSetNavigator has implemented the iDataSetPosition interface. This interface is intended to return to the location in the DataSet positioned by DataseTnavigator, which considers advanced solutions that need to access DataSet's actual DataROWS / Datacolumns. IDataSetPosition discloses a getPensionType () method, which returns an enumeration value of the current state:
• DataSetPosition.DataSet - DataSetnavigator is located on the DataSet. Calling getDataSet () will successfully return the current DataSet. Calling getDATAROW () or getDatacolumnIndex () will fail because the Navigator is not located on a particular row or column. • DataSetPosition.Row - DataSetNavigator is currently on a specific DataRow. Calling getDataSet () will return the current DataRow as a DataSet of its component. Call GetDataRow () will return the current DataRow. Call getDatacolumnIndex () will generate an error. • DataSetPosition.cell - This means that DataSetNavigator is located on a specific cell. The cell is considered a single DATAROW and a single DataColumn's intersection. Call getDataSet (), getDATAROW () or getDataColumnIndex () will be successful in this case. Back to top
summary
In preliminary testing, DataSetNavigator runs 2-50 times faster than the same conversion in XmlDATADOCUMEN, based on the complexity of the data size and style sheet to be converted. DataSetnavigator is also 2-5 times faster than the current XMLDocument or XPathDocument solution available for XMLDocument or XPathDocument solutions.
The current DataSetNavigator is quite simple and does not integrate any interesting features. A missing feature is support for namespaces. The current method is to convert DataSet into XML support namespace to serialize when they are associated with each DataSet section. The current DataSetNavigator does not provide these namespaces. Adding this feature will be quite simple, I will practice it as an interested reader.
Go to the original English page