In addition to reading existing documents, .NET makes creating an XML document from scratch very easy. The XML Creator program illustrates how this canbe done. Figures 10.14 and 10.15 show the XML Creator program in action. Whatmakes the XML Creator different from the XML Viewer is that the creator program can create XML without a pre-existing document. The XML Creator emphasizes how to create a new document and new nodes.
No new classes are necessary to create an XML document. The program uses an XmlDocument named doc, an XmlNode named theNode, and a string to hold a file name:
private XmlDocument doc; private XmlNode theNode; private string fileName = "practice.xml";
The XML document is created in the load method of the form. Creating the document is not difficult because it is simply a new instance of the XmlDocument class. However, creating the structure of the document takes some thought. For the XML Creator, I decided to build a simple address book. Figure 10.16 shows the basic document structure.
It’s a familiar refrain by now, but one that bears repeating. You need to sketch out a diagram like this before you start to code an XML document, or you’re going to get confused. Seeing the relationships between elements in your code can be difficult, but a diagram like this clarifies your intentions and makes the code much easier to write.
The code works by creating XmlElement variables for contact and person. theNode will be used as a temporary node. The first element in any document is the root (xml) node. A special method of the XmlDocument object is designed to simplify the creation of a root node: CreateXmlDeclaration() makes a root node. The parameters are almost always as listed. The first parameter stands for the XML type, which should always be "1.0". The second parameter stands for the encoding, which should always be "utf-8". The last parameter describes whether the document can stand alone. It should be "yes". After you create the root node, you still have to add it to the document. Use the AppendChild() method of the XmlNode class to add a child to a node (or to the document itself, which is also a node).
To create the other elements, use the CreateElement() method of the XmlDocument class. You will still need to use the AppendChild() method of whichever node you want to add the new child to. For example, the following code creates a node named contacts and appends it to the document object:
//create contacts node contacts = doc.CreateElement("contacts"); doc.AppendChild(contacts);
The next code fragment creates a person node and adds it as a child to contacts:
//create first address person = doc.CreateElement("person"); contacts.AppendChild(person);
When the basic structure is in place, it’s time to add some elements to the person class. Each of these elements is created just like contacts and person, but the other elements hold actual data. The easiest way to add information to a node is to set the InnerText property of the node in question. For example, here’s how I set up the name element:
theNode = doc.CreateElement("name"); theNode.InnerText = "Roger Dodger"; person.AppendChild(theNode);
The entire code for the form’s load event shows how the entire document is designed:
private void XmlCreatorForm_Load(object sender, System.EventArgs e) { //initialize doc = new XmlDocument(); XmlElement contacts; XmlElement person; //create root node theNode = doc.CreateXmlDeclaration("1.0", "utf-8", "yes"); doc.AppendChild(theNode); //create contacts node contacts = doc.CreateElement("contacts"); doc.AppendChild(contacts); //create first address person = doc.CreateElement("person"); contacts.AppendChild(person); //create address elements theNode = doc.CreateElement("name"); theNode.InnerText = "Roger Dodger"; person.AppendChild(theNode); theNode = doc.CreateElement("address"); theNode.InnerText = "123 W 4th St."; person.AppendChild(theNode); theNode = doc.CreateElement("phone"); theNode.InnerText = "123-4567"; person.AppendChild(theNode); } // end form load
As you can see from the code, it’s possible to create an XML document entirely from scratch, but you must have a solid idea of the document’s structure.
You can create additional elements in the same way you create the first one. However, after the basic structure of an element is defined, it’s much easier to make a copy of an existing element than to build one from scratch. The code in btnAdd’s click event illustrates how this is done:
private void btnAdd_Click(object sender, System.EventArgs e) { //duplicate the person node XmlNode contacts; XmlNode person; XmlNode root; root = doc.FirstChild; contacts = root.NextSibling; person = contacts.FirstChild; theNode = person.Clone(); //copy node values from text boxes theNode["name"].InnerText = txtName.Text; theNode["address"].InnerText = txtAddress.Text; theNode["phone"].InnerText = txtPhone.Text; //add the new node to contacts contacts.AppendChild(theNode); } // end btnAdd
The first part of the code recreates the document’s structure by extracting the root node, the contacts node, and the person node. Next, I created a copy of the person node, named theNode, by using the Clone() method of the person node.
I then copied the values from the text boxes over to the new node. Notice how you can use the node’s name inside braces to specify which node you want to work with.
Finally, I added the new node to contacts.
Keep your diagram handy as you’re adding nodes. The document structure expects all person nodes to be added to the contacts node. You will get unpredictable results if you add the person node somewhere else.
To see that something is happening, I decided to display the code in the text box. In principle, this is very easy to do. Every node (including doc) has an OuterXml property that returns the XML code of the node and all its children (the InnerXml property returns the XML code of the node’s children, but not the node itself). However, the formatting that is useful for human readers (with carriage returns and indentation) is usually stripped out in the internal representations of XML code because it can confuse the parser (the part of the program that navigates the XML structure). Figure 10.17 illustrates what happens when you simply copy the internal XML to the text box.
Fortunately, the XmlDocument class has a property named PreserveWhiteSpace. When this property is set to true, the document is formatted for human reading. When the property is set to false, all whitespace (carriage returns and space characters) are removed. To get the effects of the PreserveWhiteSpace property, you need to reload the document.
The btnDisplay click event takes advantage of the PreserveWhiteSpace property to display the code in a human-readable format and then convert it back to the compressed form preferred by .NET:
private void btnDisplay_Click(object sender, System.EventArgs e) { //save the current document doc.Save(fileName); //display with whitespace doc.PreserveWhitespace = true; doc.Load(fileName); txtOutput.Text = doc.OuterXml; //reload without whitespace doc.PreserveWhitespace = false; doc.Load(fileName); } // end btnDisplay
I started by saving the XML file as it currently exists to whatever file is determined by the fileName variable (set at the beginning of the program). I then set PreserveWhitespace to true, reloaded the document, and displayed the formatted version in the text box. The formatted version seemed to cause problems for some of the XML code, so I turned off PreserveWhitespace and reloaded the document again so that the version of doc in memory has no whitespace. There are other ways to automate the formatting of an XML document, but this appears to be the simplest.
3.137.212.71