XML Reading and Writing |
|
Fundamentals of Writing to an XML File |
In our introductory XML lessons, we learned to process an XML file using the Document Object Model as implemented by the XmlDocument class. To go further and make XML friendlier, the .NET Framework provides many other classes for different purposes, allowing you to create and manage nodes from custom .NET classes.
|
Besides the XmlDocument and the derived classes of XmlNode, the .NET Framework provides the XmlTextWriter class, which is derived from XmlWriter. The XmlTextWriter class works in a top-down approach to create, or deal with, the contents of an XML file. To use an XmlTextWriter object, first declare a pointer to this class and initialize the variable using one of its three constructors. If you had already created a Stream-based object such as declaring a pointer to FileStream but you didn't defined an encoding scheme, you can pass the Stream-based object to an XmlTextWriter but you must take this time to specify the encoding scheme. To support this concept, the XmlTextWriter provides a constructor with the following syntax: public: XmlTextWriter(Stream* w, Encoding enc); The first argument to this constructor can be a Stream-derived variable. The second argument specifies the encoding scheme that would be applied. The default is UTF-8. Based on this, if you want to use the UTF-8 encoding scheme, you can pass it or pass the argument as 0. If you want to use another encoding scheme, pass it to the constructor. To work from scratch, that is, to initiate a file with manually-created nodes, you can pass the desired name of the file to the XmlTextWriter constructor using the following syntax: public: XmlTextWriter(String* filename, Encoding enc); In this case, you must provide the name or path to the file, whose content you are creating, as the first argument. You must pass the desired encoding scheme as the second argument. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); } Eventually, when you have finished using the XmlTextWriter object, you must free the memory it was using by calling the XmlTextWriter::Flush() method. To release the resources that the object was using, call the XmlTextWriter::Close() method. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); }
Declaring an XmlTextWriter variable allows you to indicate that you intend to create a new XML file. With the variable ready, you can start writing the file's content. As mentioned in previous lessons, an XML file starts at the top with an XML declaration. To create this declaration, you can call the XmlTextWriter::WriteStartDocument() method. This method is overloaded with two versions. The syntax of one of them is: public: void WriteStartDocument(); This method creates a declaration, sets the XML version to 1.0, and includes the encoding scheme you specified in the constructor. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->WriteStartDocument(); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); } To end an XML file, you must close its declaration. This is done by calling the XmlTextWriter::WriteEndDocument() method. Its syntax is: public: void WriteEndDocument(); This method indicates that the XML file has ended and allows the compiler to stop reading it down. This would be done as follows: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->WriteStartDocument(); xmlTxtWriter->WriteEndDocument(); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); }
Between the XML declaration and the end of the file, that is, between the call to XmlTextWriter::WriteStartDocument() and the call to XmlTextWriter::WriteEndDocument() methods, you can create the necessary nodes of the file. As reviewed in previous lessons, the most regular node of an XML file is the element. To create an element, the XmlTextWriter class provides the WriteStartElement() method that is overloaded with various versions. One of the versions of this method and that is inherited from the XmlWriter class uses the following syntax: public: void WriteStartElement(String* localName); This method takes as argument the name of the element that will be created. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->WriteStartDocument(); xmlTxtWriter->WriteStartElement(S"Videos"); xmlTxtWriter->WriteEndDocument(); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); } As you may know from XML, every element must be closed. To close an XML element, call the XmlTextWriter::WriteEndElement() method. Its syntax is: public: void WriteEndElement(); When calling this method, always make sure that you know the element it is closing, which must corresponding to an appropriate previous call to a WriteStartElement() method. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->WriteStartDocument(); xmlTxtWriter->WriteStartElement(S"Videos"); xmlTxtWriter->WriteEndElement(); xmlTxtWriter->WriteEndDocument(); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); } This would produce: As you can see from the result, a single or the first call to the WriteStartElement() method creates the root element that is required for every XML file. This means that, after this (first) call but before its corresponding WriteEndElement() call, you can create the necessary nodes that you want to include as part of the file.
To help you create child elements of the root node, you can keep calling the XmlTextWriter::WriteStartElement() method as necessary and appropriately closing it. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->WriteStartDocument(); xmlTxtWriter->WriteStartElement(S"Videos"); xmlTxtWriter->WriteStartElement(S"Video"); xmlTxtWriter->WriteEndElement(); xmlTxtWriter->WriteEndElement(); xmlTxtWriter->WriteEndDocument(); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); } If you simply call this method as done above, the element would be empty. Based on this, the above code would produce: If you want the element to have a value, call the XmlTextWriter::WriteString() method. Its syntax is: public: void WriteString(String* text); This method must immediately follow the call to WriteStartElement() that creates a new element. It takes as argument the value for the immediately previously defined element. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->WriteStartDocument(); xmlTxtWriter->WriteStartElement(S"Videos"); xmlTxtWriter->WriteStartElement(S"Video"); xmlTxtWriter->WriteString(S"The Distinguished Gentleman"); xmlTxtWriter->WriteEndElement(); xmlTxtWriter->WriteEndElement(); xmlTxtWriter->WriteEndDocument(); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); } This would produce: If you call the XmlTextWriter::WriteStartElement() method and you want the element to have a value, remember to call the XmlTextWriter::WriteString() method, and then call the XmlTextWriter::WriteEndElement() method. An alternative is to call the XmlWriter::WriteElementString() method that comes in two versions. The syntax of one of these versions is: public: void WriteElementString(String* localName, String* value); The first argument to this method is the name of the element that will be created. The second argument is the value of the element. This method creates and closes its element. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->WriteStartDocument(); xmlTxtWriter->WriteStartElement(S"Videos"); xmlTxtWriter->WriteStartElement(S"Video"); xmlTxtWriter->WriteString(S"The Distinguished Gentleman"); xmlTxtWriter->WriteEndElement(); xmlTxtWriter->WriteElementString(S"Video", S"Fatal Attraction"); xmlTxtWriter->WriteEndElement(); xmlTxtWriter->WriteEndDocument(); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); } This would produce: In the same way, you can create the necessary elements and their child elements as necessary. Be careful to appropriately start an element and remember to close it if necessary. Here are examples: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); // The XML declaration xmlTxtWriter->WriteStartDocument(); // The root element xmlTxtWriter->WriteStartElement(S"Videos"); // Start a Video element xmlTxtWriter->WriteStartElement(S"Video"); // Create a Title child element to the Video element xmlTxtWriter->WriteStartElement(S"Title"); xmlTxtWriter->WriteString(S"The Distinguished Gentleman"); xmlTxtWriter->WriteEndElement(); // Create a Director child element to the Video element xmlTxtWriter->WriteStartElement(S"Director"); xmlTxtWriter->WriteString(S"Jonathan Lynn"); xmlTxtWriter->WriteEndElement(); // Create a Length child element to the Video element xmlTxtWriter->WriteStartElement(S"Length"); xmlTxtWriter->WriteString(S"112 Minutes"); xmlTxtWriter->WriteEndElement(); // Create a Format child element to the Video element xmlTxtWriter->WriteStartElement(S"Format"); xmlTxtWriter->WriteString(S"DVD"); xmlTxtWriter->WriteEndElement(); // Create a Rating child element to the Video element xmlTxtWriter->WriteStartElement(S"Rating"); xmlTxtWriter->WriteString(S"R"); xmlTxtWriter->WriteEndElement(); xmlTxtWriter->WriteEndElement(); // Start a Video element xmlTxtWriter->WriteStartElement(S"Video"); // Create the child elements of the second Video element xmlTxtWriter->WriteElementString(S"Title", S"Fatal Attraction"); xmlTxtWriter->WriteElementString(S"Director", S"Adrian Lyne"); xmlTxtWriter->WriteElementString(S"Length", S"120 Minutes"); xmlTxtWriter->WriteElementString(S"Format", S"VHS"); xmlTxtWriter->WriteElementString(S"Rating", S"R"); // Close a Video element xmlTxtWriter->WriteEndElement(); // Close the root element xmlTxtWriter->WriteEndDocument(); xmlTxtWriter->Flush(); xmlTxtWriter->Close(); } This would produce:
|
Practical Learning: Creating the Elements of an XML File |
using namespace System::IO; using namespace System::Xml; using namespace System::Text; |
System::Void btnSaveOrder_Click(System::Object * sender, System::EventArgs * e) { String *strFilename = 0; String *strCustomerInitials = 0; String *strCarInitials = 0; if( !this->txtFirstName->Text->Equals(S"") ) strCustomerInitials = String::Concat(strCustomerInitials, this->txtFirstName->Text->Substring(0, 1)); if( !this->txtLastName->Text->Equals(S"") ) strCustomerInitials = String::Concat(strCustomerInitials, this->txtLastName->Text->Substring(0, 1)); if( !this->txtMake->Text->Equals(S"") ) strCarInitials = String::Concat(strCarInitials, this->txtMake->Text->Substring(0, 1)); if( !this->txtModel->Text->Equals(S"") ) strCarInitials = String::Concat(strCarInitials, this->txtModel->Text->Substring(0, 1)); if( !this->txtCarYear->Text->Equals(S"") ) strCarInitials = String::Concat(strCarInitials, this->txtCarYear->Text); strFilename = String::Concat(strFilename, strCarInitials, strCustomerInitials, S".xml"); XmlTextWriter *wtrRepairOrder = new XmlTextWriter(strFilename, Encoding::UTF8); // Create the contents of the XML file // Notice that we are not making an attempt to check the values wtrRepairOrder->WriteStartDocument(); wtrRepairOrder->WriteStartElement(S"CustomerOrders"); wtrRepairOrder->WriteStartElement(S"RepairOrder"); wtrRepairOrder->WriteElementString(S"FirstName", this->txtFirstName->Text); wtrRepairOrder->WriteElementString(S"LastName", this->txtLastName->Text); wtrRepairOrder->WriteElementString(S"Address", this->txtAddress->Text); wtrRepairOrder->WriteElementString(S"City", this->txtCity->Text); wtrRepairOrder->WriteElementString(S"State", this->txtState->Text); wtrRepairOrder->WriteElementString(S"ZIPCode", this->txtZIPCode->Text); wtrRepairOrder->WriteElementString(S"Make", this->txtMake->Text); wtrRepairOrder->WriteElementString("Model", this->txtModel->Text); wtrRepairOrder->WriteElementString(S"CarYear", this->txtCarYear->Text); wtrRepairOrder->WriteElementString(S"ProbDescription", this->txtProblem->Text); wtrRepairOrder->WriteElementString(S"PartName1", this->txtPartName1->Text); wtrRepairOrder->WriteElementString(S"UnitPrice1", this->txtPartUnitPrice1->Text); wtrRepairOrder->WriteElementString(S"Quantity1", this->txtPartQuantity1->Text); wtrRepairOrder->WriteElementString(S"SubTotal1", this->txtPartSubTotal1->Text); wtrRepairOrder->WriteElementString(S"PartName2", this->txtPartName2->Text); wtrRepairOrder->WriteElementString(S"UnitPrice2", this->txtPartUnitPrice2->Text); wtrRepairOrder->WriteElementString(S"Quantity2", this->txtPartQuantity2->Text); wtrRepairOrder->WriteElementString(S"SubTotal2", this->txtPartSubTotal2->Text); wtrRepairOrder->WriteElementString(S"PartName3", this->txtPartName3->Text); wtrRepairOrder->WriteElementString(S"UnitPrice3", this->txtPartUnitPrice3->Text); wtrRepairOrder->WriteElementString(S"Quantity3", this->txtPartQuantity3->Text); wtrRepairOrder->WriteElementString(S"SubTotal3", this->txtPartSubTotal3->Text); wtrRepairOrder->WriteElementString(S"PartName4", this->txtPartName4->Text); wtrRepairOrder->WriteElementString(S"UnitPrice4", this->txtPartUnitPrice4->Text); wtrRepairOrder->WriteElementString(S"Quantity4", this->txtPartQuantity4->Text); wtrRepairOrder->WriteElementString(S"SubTotal4", this->txtPartSubTotal4->Text); wtrRepairOrder->WriteElementString(S"PartName5", this->txtPartName5->Text); wtrRepairOrder->WriteElementString(S"UnitPrice5", this->txtPartUnitPrice5->Text); wtrRepairOrder->WriteElementString(S"Quantity5", this->txtPartQuantity5->Text); wtrRepairOrder->WriteElementString(S"SubTotal5", this->txtPartSubTotal5->Text); wtrRepairOrder->WriteElementString(S"Job1", this->txtJobDescription1->Text); wtrRepairOrder->WriteElementString(S"JobPrice1", this->txtJobPrice1->Text); wtrRepairOrder->WriteElementString(S"Job2", this->txtJobDescription2->Text); wtrRepairOrder->WriteElementString(S"JobPrice2", this->txtJobPrice2->Text); wtrRepairOrder->WriteElementString(S"Job3", this->txtJobDescription3->Text); wtrRepairOrder->WriteElementString(S"JobPrice3", this->txtJobPrice3->Text); wtrRepairOrder->WriteElementString(S"Job4", this->txtJobDescription4->Text); wtrRepairOrder->WriteElementString(S"JobPrice4", this->txtJobPrice4->Text); wtrRepairOrder->WriteElementString(S"Job5", this->txtJobDescription5->Text); wtrRepairOrder->WriteElementString(S"JobPrice5", this->txtJobPrice5->Text); wtrRepairOrder->WriteElementString(S"TotalParts", this->txtTotalParts->Text); wtrRepairOrder->WriteElementString(S"TotalLabor", this->txtTotalLabor->Text); wtrRepairOrder->WriteElementString(S"TaxRate", this->txtTaxRate->Text); wtrRepairOrder->WriteElementString(S"TaxAmount", this->txtTaxAmount->Text); wtrRepairOrder->WriteElementString(S"TotalOrder", this->txtTotalOrder->Text); wtrRepairOrder->WriteElementString(S"Recommendations", this->txtRecommendations->Text); wtrRepairOrder->WriteEndElement(); wtrRepairOrder->WriteEndElement(); wtrRepairOrder->WriteEndDocument(); wtrRepairOrder->Flush(); wtrRepairOrder->Close(); // Reset the form in case the user wants to add a new car btnResetOrder_Click(sender, e); } |
If you are creating text-intensive document and you want to save it as an XML file, for example if you have declared a variable of type TextWriter-derived class (such as StringWriter or StreamWriter), you can use that file to initialize the XmlTextWriter variable. To support TextWriter documents, the XmlTextWriter provides a constructor with the following syntax: public: XmlTextWriter(TextWriter* w); This constructor expects as argument TextWriter-based object. This means that you should have defined the TextWriter object prior to passing it to this constructor. This also implies that the TextWriter was used to specify the encoding scheme that would be used. Here is an example: |
System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { FileStream *fleStream = new FileStream(S"Videos.xml", FileMode::Create, FileAccess::Write, FileShare::None); StreamWriter *stmWriter = new StreamWriter(fleStream); XmlTextWriter *xmlTxtWriter = new XmlTextWriter(stmWriter); stmWriter->Flush(); stmWriter->Close(); }
To actually write the contents of the document, you can create each paragraph by calling the XmlTextWriter::WriteStartElement() method the same way we did earlier. Here is an example: |
System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { FileStream *fleStream = new FileStream(S"Memorandum.xml", FileMode::Create, FileAccess::Write, FileShare::None); StreamWriter *stmWriter = new StreamWriter(fleStream); XmlTextWriter *xmlTxtWriter = new XmlTextWriter(stmWriter); xmlTxtWriter->Formatting = Formatting::Indented; xmlTxtWriter->WriteStartDocument(); xmlTxtWriter->WriteStartElement(S"ToAllEmployees"); for(int i = 0; i < this->txtEditor->Lines->Length; i++) { xmlTxtWriter->WriteStartElement(S"Notice"); xmlTxtWriter->WriteString(this->txtEditor->Lines[i]->ToString()); xmlTxtWriter->WriteEndElement(); } xmlTxtWriter->WriteEndDocument(); stmWriter->Flush(); stmWriter->Close(); }
Once an XML file exists, you can read it to retrieve the values of its nodes. To support opening an XML file and reading its contents, the .NET Framework provides the XmlTextReader class that is derived from the XmlReader class. The XmlTextReader class is equipped with all the necessary properties and methods to explore the contents of an XML file. Like XmlTextWriter, the XmlTextReader class reads a file from top to bottom without going back up once it has passed a node. This means that it reads each node once and passes to the next.
To use an XML text reader, declare a pointer to XmlTextReader and initialize it with one of its constructors. This class is equipped with 14 constructors. If you want to open a file whose name or path you know, use the following constructor: public: XmlTextReader(String* url); This constructor takes as argument the name or path to an XML file. If the file is found, then it would be opened. If the file doesn't exist or there is an error in the string that specifies its path, the compiler would throw an XmlException exception.
After declaring an XmlTextReader variable, you can start reading the content of the file. To support this, you can call the XmlTextReader::Read() method. Its syntax is: public: bool Read(); As mentioned previously, the file is read from top to bottom. Based on this, when you call the Read() method, it reads the first node, moves to the next, and so on until it reaches the end of the file. While reading the file, every time this method reaches a node, you can find out what type of node it is by checking the XmlTextReader::NodeType property. This can help you take specific action if the reached node meets a certain criterion. As reviewed in our introductions to XML, each node has a name and possibly a value. You can find out the name of a node by checking the XmlTextReader::Name property. To know the value of a node, retrieve its XmlTextReader::Value property. |
Practical Learning: Reading the Elements of an XML File |
System::Void btnOpenOrder_Click(System::Object * sender, System::EventArgs * e) { XmlTextReader *rdrRepairOrder; try { if( this->openFileDialog1->ShowDialog() == DialogResult::OK ) { rdrRepairOrder = new XmlTextReader(this->openFileDialog1->FileName); // Scan the XML file while (rdrRepairOrder->Read()) { // every time you find an element, find out what type it is // If you find text, put it in the combo box' list if( XmlNodeType::Element && rdrRepairOrder->Name->Equals(S"FirstName") ) { this->txtFirstName->Text = rdrRepairOrder->ReadElementString(S"FirstName"); this->txtLastName->Text = rdrRepairOrder->ReadElementString(S"LastName"); this->txtAddress->Text = rdrRepairOrder->ReadElementString(S"Address"); this->txtCity->Text = rdrRepairOrder->ReadElementString(S"City"); this->txtState->Text = rdrRepairOrder->ReadElementString(S"State"); this->txtZIPCode->Text = rdrRepairOrder->ReadElementString(S"ZIPCode"); this->txtMake->Text = rdrRepairOrder->ReadElementString(S"Make"); this->txtModel->Text = rdrRepairOrder->ReadElementString("Model"); this->txtCarYear->Text = rdrRepairOrder->ReadElementString(S"CarYear"); this->txtProblem->Text = rdrRepairOrder->ReadElementString(S"ProbDescription"); this->txtPartName1->Text = rdrRepairOrder->ReadElementString(S"PartName1"); this->txtPartUnitPrice1->Text = rdrRepairOrder->ReadElementString(S"UnitPrice1"); this->txtPartQuantity1->Text = rdrRepairOrder->ReadElementString(S"Quantity1"); this->txtPartSubTotal1->Text = rdrRepairOrder->ReadElementString(S"SubTotal1"); this->txtPartName2->Text = rdrRepairOrder->ReadElementString(S"PartName2"); this->txtPartUnitPrice2->Text = rdrRepairOrder->ReadElementString(S"UnitPrice2"); this->txtPartQuantity2->Text = rdrRepairOrder->ReadElementString(S"Quantity2"); this->txtPartSubTotal2->Text = rdrRepairOrder->ReadElementString(S"SubTotal2"); this->txtPartName3->Text = rdrRepairOrder->ReadElementString(S"PartName3"); this->txtPartUnitPrice3->Text = rdrRepairOrder->ReadElementString(S"UnitPrice3"); this->txtPartQuantity3->Text = rdrRepairOrder->ReadElementString(S"Quantity3"); this->txtPartSubTotal3->Text = rdrRepairOrder->ReadElementString(S"SubTotal3"); this->txtPartName4->Text = rdrRepairOrder->ReadElementString(S"PartName4"); this->txtPartUnitPrice4->Text = rdrRepairOrder->ReadElementString(S"UnitPrice4"); this->txtPartQuantity4->Text = rdrRepairOrder->ReadElementString(S"Quantity4"); this->txtPartSubTotal4->Text = rdrRepairOrder->ReadElementString(S"SubTotal4"); this->txtPartName5->Text = rdrRepairOrder->ReadElementString(S"PartName5"); this->txtPartUnitPrice5->Text = rdrRepairOrder->ReadElementString(S"UnitPrice5"); this->txtPartQuantity5->Text = rdrRepairOrder->ReadElementString(S"Quantity5"); this->txtPartSubTotal5->Text = rdrRepairOrder->ReadElementString(S"SubTotal5"); this->txtJobDescription1->Text= rdrRepairOrder->ReadElementString(S"Job1"); this->txtJobPrice1->Text = rdrRepairOrder->ReadElementString(S"JobPrice1"); this->txtJobDescription2->Text= rdrRepairOrder->ReadElementString(S"Job2"); this->txtJobPrice2->Text = rdrRepairOrder->ReadElementString(S"JobPrice2"); this->txtJobDescription3->Text= rdrRepairOrder->ReadElementString(S"Job3"); this->txtJobPrice3->Text = rdrRepairOrder->ReadElementString(S"JobPrice3"); this->txtJobDescription4->Text= rdrRepairOrder->ReadElementString(S"Job4"); this->txtJobPrice4->Text = rdrRepairOrder->ReadElementString(S"JobPrice4"); this->txtJobDescription5->Text = rdrRepairOrder->ReadElementString(S"Job5"); this->txtJobPrice5->Text = rdrRepairOrder->ReadElementString(S"JobPrice5"); this->txtTotalParts->Text = rdrRepairOrder->ReadElementString(S"TotalParts"); this->txtTotalLabor->Text = rdrRepairOrder->ReadElementString(S"TotalLabor"); this->txtTaxRate->Text = rdrRepairOrder->ReadElementString(S"TaxRate"); this->txtTaxAmount->Text = rdrRepairOrder->ReadElementString(S"TaxAmount"); this->txtTotalOrder->Text = rdrRepairOrder->ReadElementString(S"TotalOrder"); this->txtRecommendations->Text = rdrRepairOrder->ReadElementString(S"Recommendations"); } } } } catch(XmlException *) { MessageBox::Show(S"The file name you provided is not valid"); } __finally { rdrRepairOrder->Close(); } } |
Consider a valid XML file such as the following, opened in Notepad: If you were asked to examine this file, you can see that its crowded words make it difficult to read. To include a white space when writing to the file, you can call the XmlTextWriter::WriteWhiteSpace() method. Its syntax is: public: void WriteWhitespace(String* ws); Besides white spaces, indentation consists of setting empty space on the left of child nodes to make the file easier to read. Based on this, indentation is not a requirement but a convenience. While the WriteWhiteSpace() method allows you to explicitly create a white space in the file, the XmlTextWriter class is equipped with the Formatting property. This property is a value of the Formatting enumerator. The Formatting enumerator has two members. The Indented value ensures that each child node would be indented from its parent. If you manually create an XML file, whether using Notepad, Visual Studio, or another text editor, you can indent the nodes as you see fit. To let the compiler know that you want the nodes to be indented, assign the Formatting::Indented member to its Formatting property. Here is an example: System::Void btnSave_Click(System::Object * sender, System::EventArgs * e) { XmlTextWriter *xmlTxtWriter = new XmlTextWriter(S"Videos.xml", Encoding::UTF8); xmlTxtWriter->Formatting = Formatting::Indented; xmlTxtWriter->Flush(); xmlTxtWriter->Close(); } If you manually create an XML file, you can specify the number of empty spaces on the left of a node by pressing the Space bar a few times before typing the node. Most people use 2 or 4 characters for the indentation. If you are programmatically creating the file, to specify the number of characters that should be used during indentation, assign the desired integer to the XmlTextWriter::Indentation property. If you don't use this property, the compiler would use two characters. You can also find out the number of characters used for indentation by retrieving the value of this property. As mentioned above, indentation consists of entering white spaces on the left of child nodes. Instead of empty spaces, if you want to use another character, assign it to the XmlTextWriter::IndentChar property.
|
Practical Learning: Indenting XML Nodes |
System::Void btnSaveOrder_Click(System::Object * sender, System::EventArgs * e) { . . . No Change if( this->saveFileDialog1->ShowDialog() == DialogResult::OK ) { XmlTextWriter *wtrRepairOrder = new XmlTextWriter(this->saveFileDialog1->FileName, Encoding::UTF8); wtrRepairOrder->Formatting = Formatting::Indented; wtrRepairOrder->Indentation = 4; . . . No Change } } |
|
||
Home | Copyright © 2004-2010 FunctionX, Inc. | |
|