Reading and writing in an XML file with XPath PDF Print E-mail
User Rating: / 1
PoorBest 
Thursday, 10 July 2008

1. Prerequisite
-- Knowledge of C # language.
-- The sources of downloadable program-example here: src Here.

2. What is this tutorial?
This tutorial shows how to search, insert, modify and delete XML data using the technology XPath. For more information: Definition XPath. XPath has the following advantages: - Performance: XPath allows you to quickly process XML documents.
-- The clarity and concision of code: XPath can encode a single operation in less lines than other methods. The first part focuses on the extraction of data contained in an XML file.
The second part deals with publishing an XML file.
This tutorial is based on a concrete project.
The XSD schemas are not used here in order not to make too complex this tutorial.
However, research and publishing data in an XML file linked to a scheme XSD are not difficult to learn techniques once that what is presented in this tutorial is acquired.

3. Introduction of draft
3.1. Features

The project is a Client Manager Basic.
Every record XML "Client.xml" contains the following fields: ID, Name, Name, Telephone, DateInscription and Status.
The proposed program performs the following actions:
-- Search data on a customer from his ID, name, phone or recording date.
-- Insert, editing and deleting data about a client.

3.2. Technically speaking
The project is divided into three layers, which manages the interface (Interface), another which contains all classes to access the data (DataLayer) and a final which contains classes that contain data on a customer ( StructureLibrary).
The interface is composed of two sheets.

4. Notions XML Base
This section describes the concepts XML to know to understand the rest of this tutorial.
The following XML file is used to explain the following:
<? xml version = "1.0" encoding = "utf-8"?>
<Clients>
   <Client Id="1">
     <Prenom> Jean-Michel </ Name>
     <Name> Laroche </ Name>
     <Telephone> 027854632 </ Phone>
     <DateInscription> 02/06/2007 </ DateInscription>
     Activated <Status> </ Status>
   </ Client>
   <Client Id="2">
     <Prenom> Smith </ Name>
     <Name> Cordwainer </ Name>
     <Telephone> 024213296 </ Phone>
     <DateInscription> 12/06/2007 </ DateInscription>
     Activated <Status> </ Status>
   </ Client>
   <Client Id="3">
     <Prenom> Frank </ Name>
     <Name> Herbert </ Name>
     <Telephone> 022354562 </ Phone>
     <DateInscription> 08/07/2007 </ DateInscription>
     Activated <Status> </ Status>
   </ Client>
   <Client Id="4">
     <Prenom> Phillipe </ Name>
     <Name> Dick </ Name>
     <Telephone> 023254789 </ Phone>
     <DateInscription> 12/07/2007 </ DateInscription>
     Deleted <Status> </ Status>
   </ Client>
   <MaxID> 4 </ MaxID>
</ Customers>

4.1. Knots and beacons
The node (node) is the basic unit of an XML file.
A node is a field bounded by tags may contain a value, attributes and sub-nodes (nodes-children).
In the XML file above, <Clients> ...</ Clients>, <Client id="1"> ...</ Client>, <Prenom> ...</ First >,... are nodes.
The declaration of a node, with the name "Phone" and as having value "99999" is this: <Telephone> 99999 </ Phone>.
Any element of the form is called <UnNom> tag (markup).
A node should be delimited by two tags this way: <NomDuNoeud> Value From Node </ NomDuNoeud>.
It is not required to give a value to a node (node empty).
The value (text) of a node is the text between the two tags that surround this node and any text values its child nodes.
Declaring several knots with the same name is allowed.

4.2. Racine

The root of an XML document ( "root" in English) is a fictitious node that is not stated in the document.
The latter is the knot with the hierarchical level is higher.
The following info <xml version = "1.0" encoding = "utf-8"?> is not regarded as a node.
It is a statement that defines the version of an XML file and its encoding (UTF-8, ISO ,...).
4.3. Knots knots child and parent (or ancestor)
The crux "y" is a child node (child-node) node "x" if the node "y" is contained in the node "x".
In our file-example, the node <Prenom> Smith </ Name> is a child node node <Client id="2"> ...</ Client>.
The crux "y" is the parent node (or its ancestor, ancestor / parent-node) node "x" if the node "y" node contains "x".
In the previous example, Node <Client id="2"> ...</ Client> is the ancestor node <Prenom> Smith </ Name>.

4.4. Attributes
The attribute (attribute) of a node is a node declared inside the first tag that defines this node.
In the file-example, each node Client has an attribute "id."

5. Syntax XPath
5.1. Background

The context is the repository on which research is based.
While browsing the tree in an XML file, subject to the navigation is still positioned on a node, this node is called context.
An XPath expression preceded by "." Based on the current context.
Ex: ". / Author" selects all child nodes named "author" from the current context.
An expression using XPath context as the root of the XML document, is preceded by "/".
Ex: "/ book" selects all child nodes called "book" using context as the root of the document.
If the search covers all elements with a given name without taking into account their seniority, XPath expression is preceded by "//".
Ex: "/ / Friend" selects all the nodes in the documents named "Friend". If research should focus on all the nodes of a given name but must also rely on the current context, it should be preceded by the phrase XPath ".//".
Ex: "/ / Pricing selects ALL nodes that have the name in the paper while". / / Pricing selects only the nodes that children of current context with the name "Price".

5.2. Selection knots / attributes
To select all the nodes-children of current context, it should use the symbol "*" which means "All nodes (such element or attribute (if preceded by "@"))".
If the selection covers all types of existing nodes, you must use node () * and not merely limited to nodes type elements and attributes.
Ex: "./*" selects all the nodes-type children's element of the current context.
To select one or more attributes, you must use the symbol "@".
It precedes the name of the attribute sought.
Ex: ". / Book / @ price" selects all the attributes price nodes book (based on the current context).

5.3. Conditions
To express a condition on a search, you must use one (to) block (s) delimited (s) in brackets [...].
Examples:
"/ / Book [price]" selects all the nodes in the document with a child named node price regardless of the value of the latter.
"/ / Book [price ='16 ']" selects all the nodes in the document with a child named node price whose value is exactly 16.
"/ / Book [1]" selects only the first node Book among the nodes is appointing Book in an XML document.
"/ / Book [price> 15]" selects all book knots of material whose child node price has a value greater than 15.
"/ / Book [@ author! = 'Poor author'] / price" selects all knots price for which the value of the author attribute their parent node Book is different from "A bad author."
Besides, the logical operators "or" and "and" can make several conditions.
All these theoretical concepts will be applied to a case in the following sections.
The idea is advised to read the MSDN on XPath syntax (link: MSDN Library).
It is clear and provide many details on the XPath syntax and many examples.

6. Look for data with XPath
6.1. XML file structure

The XML file used is this:
Clients.xml
<? xml version = "1.0" encoding = "utf-8"?>
<Clients>
   <Client Id="1">
     <Prenom> Jean-Michel </ Name>
     <Name> Laroche </ Name>
     <Telephone> 027854632 </ Phone>
     <DateInscription> 02/06/2007 </ DateInscription>
     Activated <Status> </ Status>
   </ Client>
   <Client Id="2">
     <Prenom> Smith </ Name>
     <Name> Cordwainer </ Name>
     <Telephone> 024213296 </ Phone>
     <DateInscription> 12/06/2007 </ DateInscription>
     Activated <Status> </ Status>
   </ Client>
   <Client Id="3">
     <Prenom> Frank </ Name>
     <Name> Herbert </ Name>
     <Telephone> 022354562 </ Phone>
     <DateInscription> 08/07/2007 </ DateInscription>
     Activated <Status> </ Status>
   </ Client>
   <Client Id="4">
     <Prenom> Phillipe </ Name>
     <Name> Dick </ Name>
     <Telephone> 023254789 </ Phone>
     <DateInscription> 12/07/2007 </ DateInscription>
     Deleted <Status> </ Status>
   </ Client>
   <MaxID> 4 </ MaxID>
</ Customers>

Each node Client represents a client and contains five knots-children whose names clearly indicate what their values réprésentent, if this is the crux Status, which takes as its value is "Activated" or "Deleted".

 If its value is Deleted, this node will be ignored in every search.
The approach is not to permanently delete a node allows the restoration of unintentional deletions and also not to reassign an ID that has already been used before.
Indeed, it is not shouaitable a user whose account was deleted wants to reconnect with the ID that was provided at registration and does not realize that the account to which it tries to connect n ' is actually more to it.

The crux MaxID helps ease the insertion of a new customer in the XML file because without this node, the search for the first ID unused is more complicated.

6.2. Find a node from its attributes
Search for a score from its ID (from an attribute)
public static StructureLibrary.Client SearchCustomerById (string ID)
         (
             / * Declares it creates an instance of variables needed for research * /
             Customer StructureLibrary.Client = new StructureLibrary.Client ();
             XPathDocument XPathDocu = new XPathDocument ( "Clients.xml");
             XPathNavigator Navigator;
             XPathNodeIterator Nodes;
             / * It affects the false variable NoMatches to verify thereafter
              * If the search was successful * /
             Customer.NoMatches = false;
             / * It creates a browser * /
             Navigator XPathDocu.CreateNavigator = ();
             / * Created by the XPath expression research score from ID * /
             ExpXPath = "/ / Client [@ id = '" + ID +' and Status! = 'Deleted'] ";
             / * We launch research * /
             Nodes Navigator.Select = (Navigator.Compile (ExpXPath));
             / * Check whether the research was fruitful * /
             if (Nodes.Count! = 0)
             (
                 Nodes.MoveNext () / / NOTE: Necéssaire to place it on the node sought
                 / * Encoding data into the Customer class * /
                 Customer.ID = ID; / * No need to look this up because this is our
                                    * Search criterion, it can be directly
                                    * Encoder. * /
                 Nodes.Current.MoveToFirstChild (); / * It moves on the first node
                                                    * Child "First" * /
                 Customer.FirstName = Nodes.Current.Value;
                 Nodes.Current.MoveToNext () / / It moves on the next node "Name"
                 Customer.Name = Nodes.Current.Value;
                 Nodes.Current.MoveToNext ();
                 Customer.PhoneNumber = Nodes.Current.Value;
                 Nodes.Current.MoveToNext ();
                 Customer.RegistrationDate = Nodes.Current.Value;

             )
             / * If any customer has been found * /
             Else
             (
                 Customer.NoMatches = true;
             )
             / * Divert all data in an instance of class "Client" * /
             Customer return;
         )

This function returns a class and allows Client from its only argument (which is the customer ID) to recover any data on this score.

First, an instance of class Client defined in Structures.cs is created, this class brings together in a single subject all data on a client.

The properties of this class are clear and sufficiently discussed in the source code, they will not be explained here.

Then, an instance of class XPathDocument is created, this class allows loading (the memory) of XML document in which there are data on customers.

The manufacturer of an XPathDocument takes one argument: the path to the XML file that will be analysed.

The class XPathNavigator can move in knots and to remove the content.

The XPath expression works as follows:
while ignoring nodes declared as deleted (Status! = 'Deleted'), it will search all our knots "Client" of the document as having value for the ID attribute past argument that the method SearchCustomerByID.

Once the XPath expression created, the search is launched and all nodes meeting the search conditions (if any) are placed in a XPathNodeIterator class facilitating navigation in knots found in this way.

The research carried out with the method Select a XPathNavigator.
Moreover, the expression is compiled to make it faster through XPathNavigator.Compile (string XPathExp).

The number of nodes found is given through the Count property of a XPathNode Iterator.
If no node has been reached, the True value is assigned to Client.NoMatches.

If at least one node has been found, XPathNodeIterator is placed above using the method MoveNext (attention, forget to use this method returns erroneous results during extraction or modification of data).

Once positioned on the node Client, the method MoveToFirstChild () is invoked, it places the XPathNodeIterator on the first child node (the order corresponds to the statements of nodes in the document).

Then, the value of the node on which the XPathNodeIterator is positioned is encoded (here "First").
To navigate in knots at the same level (hierarchical) in the document should use the method MoveToNext (), once again, XPathNodeIterator move to the next node based on the order of statements nodes in the document.

When all data is encoded, the function returns a class SearchCustomerByID Client which contains all the data on the client wanted.

6.3. Find a node from a child node
Find a node from one of its child nodes
         public static StructureLibrary.Client SearchCustomerByNode (string Criteria, string Node)
         (
             / * For comments, see SearchCustomerByID * /
             Customer StructureLibrary.Client = new StructureLibrary.Client ();
             XPathDocument XPathDocu = new XPathDocument ( "Clients.xml");
             XPathNavigator Navigator;
             XPathNodeIterator Nodes;
             Customer.NoMatches = false;
             Navigator XPathDocu.CreateNavigator = ();
             ExpXPath = "Clients / Client [" Criteria +"='" + + + Node 'and Status! =' Deleted '] ";
             Nodes Navigator.Select = (Navigator.Compile (ExpXPath));
             if (Nodes.Count! = 0)
             (
                 Nodes.MoveNext ();
                 Customer.ID Nodes.Current.GetAttribute = ( "id", "");
                 Nodes.Current.MoveToFirstChild ();
                 Customer.FirstName = Nodes.Current.Value;
                 Nodes.Current.MoveToNext ();
                 Customer.Name = Nodes.Current.Value;
                 Nodes.Current.MoveToNext ();
                 Customer.PhoneNumber = Nodes.Current.Value;
                 Nodes.Current.MoveToNext ();
                 Customer.RegistrationDate = Nodes.Current.Value;
             )
             Else
             (
                 Customer.NoMatches = true;
             )
             Customer return;
         )

This code can find a node from any of its child nodes.
The method takes two arguments SearchCustomerByNode respectively on behalf of the child node on which research will be based for and the value that it should have.

NOTE / REMINDER: The condition of XPath expression is preceded by the symbol @, which indicates that the condition relates to a node.

Ex : If the name of the child node is' First 'and its expected value' Toto 'then the expression will take this form: "Customers / Client [First =' Toto 'and Status! =' Deleted ']"

The encoding data into an instance of the class score is similar to the function SearchCustomerByID except that they must find the ID attribute before the encoder because it is no longer the search criteria.

To do so, it is necessary to invoke the procedure GetAttribute which takes two arguments, the first being the name of the attribute sought and the second being the space-name (namespace) node (if any space-name is declared in the XML file, it should let the second argument empty).

7. Editing XML data
7.1. Editing XML data

Edit XML data already existing
public static Boolean EditXMLData (StructureLibrary.Client Customer)
         (
             / * It uses a XmlDocument and not an XPathDocument because the latter can not
              * No data editing XML. * /
             XmlDocument XmlDoc = new XmlDocument ();
             XPathNavigator Navigator;
             XPathNodeIterator Nodes;
             XmlDoc.Load ( "Clients.xml");
             Navigator XmlDoc.CreateNavigator = ();
             ExpXPath = "/ / Client [@ id =" Customer.ID + + 'and Status! =' Deleted '] ";
             Nodes Navigator.Select = (Navigator.Compile (ExpXPath));
             if (Nodes.Count! = 0)
             (
                 / * Encoding new data * /
                 Nodes.MoveNext ();
                 Nodes.Current.MoveToFirstChild ();
                 Nodes.Current.SetValue (Customer.FirstName);
                 Nodes.Current.MoveToNext (XPathNodeType.Element);
                 Nodes.Current.SetValue (Customer.Name);
                 Nodes.Current.MoveToNext (XPathNodeType.Element);
                 Nodes.Current.SetValue (Customer.PhoneNumber);
                 Nodes.Current.MoveToNext (XPathNodeType.Element);
                 Nodes.Current.SetValue (Customer.RegistrationDate);
                 XmlDoc.Save ( "Clients.xml");
                 return true;
             )
             Else
             (
                 return false;
             )
         )

To edit data and not simply to retrieve them, you must use an XmlDocument in place of an XPathDocument.
The purpose XPathDocument not allowed to retrieve data, which is why the use of a XmlDocument is necessary because it allows editing of data.
The processes that create a XmlDocument differs slightly from that instantiates an XPathDocument.
Indeed, the manufacturer of XmlDocument makes no argument, the document is loaded with the Load method of XmlDocument.
However, the research process is quite the same.

Once positioned on a node, XPathNodeIterator moves on the first node to child through the method MoveToFirstChild ().
The change in the value of a node s'éxécute using the method SetValue (string NewValue) whose only argument is the new value to be assigned to node.
Once all the data published, simply save the document with the Save method (string FilePath) XmlDocument argument that takes the path will be created where the new file (in this case, the program overwrites the last file).

7.2. Insertion of new nodes / attributes in a document XML

Insertion of new data in an XML document
public static Boolean InsertNewCustomer (StructureLibrary.Client Customer)
         (
             XmlDocument XmlDoc = new XmlDocument ();
             XPathNavigator Navigator;
             XPathNodeIterator Nodes;
             Int32 ID; / * Variable used to find out what is the ID that must be allocated to the new
                        * Node created * /
             XmlDoc.Load ( "Clients.xml");
             Navigator XmlDoc.CreateNavigator = ();
             / * Search MaxID node to determine what will be the new ID
              * Client. * /
             ExpXPath = "/ / MaxID";
             Nodes Navigator.Select = (Navigator.Compile (ExpXPath));
             Nodes.MoveNext ();
             / * Place the ID's highest document in the variable ID * /
             ID = Nodes.Current.ValueAsInt;
             / * Increase the value of the node MaxID because once our new node
              * Created, the ID's highest document will also be incremented * /
             Nodes.Current.SetValue ((ID 1). ToString ());
             / * It will be installed on the node with the highest ID * /
             ExpXPath = "/ / Client [@ id = '" + ID.ToString ()+"']";
             Nodes Navigator.Select = (Navigator.Compile (ExpXPath));
             if (Nodes.Count! = 0)
             (
                 Nodes.MoveNext ();
                 / * It creates the principal node (Client). * /
                 Nodes.Current.InsertElementAfter ( "", "Client," "" "");
                 / * It will be installed on the node created. * /
                 Nodes.Current.MoveToNext (XPathNodeType.Element);
                 ID + +; / * ID increments so its value is identical to that is
                        * In the node MaxID. * /
                 / * Encoding data * /
                 Nodes.Current.CreateAttribute ( "", "id", "" ID.ToString ());
                 Nodes.Current.AppendChildElement ( "", "First", "" Customer.FirstName);
                 Nodes.Current.AppendChildElement ( "", "Name", "" Customer.Name);
                 Nodes.Current.AppendChildElement ( "", "Phone", "", Customer.PhoneNumber);
                 Nodes.Current.AppendChildElement ( "", "DateInscription", "" Customer.RegistrationDate);
                 Nodes.Current.AppendChildElement ( "", "Status", "", "Activated");
                 XmlDoc.Save ( "Clients.xml");
                 return true;
             )
             Else
             (
                 return false;
             )
         )

The first step is to recover the value of the node MaxID to know what ID affect the future node.
To do that, the XPathNodeIterator takes place on this node and extract the value that is assigned to the variable ID.

The value of the node MaxID is incremented in order to bring it into line with the ID of the node to be established thereafter.

Then, XPathNodeIterator is placed over the knot with the ID attribute the highest (that the value of which corresponds with that of the variable ID).

Once the XPathNodeIterator positioned above, a new node Client is created, the latter is after all other nodes.

The creation of a new node is using the method InsertElementAfter (prefix string, string LocalName, string NameSpaceURI, string Value).

In this case, only the LocalName argument is interesting because it is this argument that determines the name of the future node.

The method info InsertElementAfter inserts the new node after node on which the XPathNodeIterator is currently positioned.

To add a new node before the current node, you must use the method InsertElementBefore who naturally takes the same arguments as his counterpart.

The next step is to place the XPathNodeIterator on the new node created with the method MoveToNext (XPathNodeType NodeType).

The variable is incremented ID in order to bring it into line with that of MaxID node.
Finally, attribute ID and child nodes are encoded with methods CreateAttribute and AppendChildElement.

The method CreateAttribute creates an attribute and takes the same arguments that the method InsertElementAfter.

The method AppendChildElement creates a node-child and also takes the same arguments that the method InsertElementAfter.

Once an attribute or a child node created, the XPathNodeIterator does not automatically place above.

7.3. Deleting a node and its child nodes.

There is no function in the program-which allows for example permanently delete a node.
Why? Simply because when a node is permanently destroyed, there is no way to restore (a rollback).

The program does not, therefore, the node in question but affects the value "Deleted" in its node Status.

Thus, the customer is ignored in all research and appears as deleted but there is always room to reactivate its account.

However, there is obviously a way to permanently delete a node or an attribute.
The method of removing a node and its child nodes is very simple: just put a XPathNodeIterator on the node to remove and call the method DeleteSelf which makes no argument.

If the operation is a success, XPathNodeIterator (or XpathNavigator) is automatically placed on the ancestor node removed.

8. Possible improvements programme example
A series of improvements to the program-example is offered as an exercise:
-- When the program searches for a client by his first name, it takes into account only the first result, or several customers may have the same name.

It is therefore preferable that the program displays the total number of results and allows the user to navigate among them (for example by returning an array of classes "Client").
-- Create a function to reactivate a client's account by changing the value of its node Status.

9. Conclusion
The technology allows XPath to write a code clear and concise while maintaining application performance.
Moreover, learning XPath does not require much investment.
Finally, this technology is built on other platforms such as Java.

10. Acknowledgments
Thanks to Erwy for his comments on the substance of the article.
Thanks to Cardi for his remarks.
Thanks to Skalp for his remarks on spelling.
Thanks to Bernard Determe for his remarks on the style of the article.
And thank you to all the team developpez.com which allowed me to host this article.

 
< Prev   Next >
School Joomla Templates and Joomla Tutorials