XML |
The language XML is simple language than can be used to store and exchange information. As XML is a standard language, it is possible to exchange information between two computers with a different operating system, or between two programs written in different languages. Thus, XML defines an standard to store and exchange data. |
XML File |
XML can be used to create an XML file. An XML file is a text file with extension .xml that follows some simple rules. An xml file can be used to store and exchange information. For instance, a company may provide an XML file to report taxes. The first line of an XML file must be: <?xml version="1.0" encoding="utf-8"?>. XML data can be created by concatenating text while replacing some special characters. XML data must be converted to UTF-8 before saving to disk or sending over the Internet. |
XML on the Internet |
XML is typically using exchange over the Internet to perform operations and transactions. XML es típicamente usado para intercambiar información en la Internet para hacer operaciones y transacciones. |
Problem 1 |
Use notepad to create an XML file called hello.xml to store a message. Be sure to save the file as hello.xml with encoding UTF8. By default notepad will save the file as helo.xml.txt, so you must select the option: All Files (*.*) as shown. Observe that an XML file is composed of tags. These tags are declared using the symbols: > and <. HTML uses standard tags, on the other hand, XML allows the user to define his own tags. For instance in the file helo.xml, the tag <message> was defined for us. |
Tip |
You may use several programs to open an XML file. Microsoft Visual Studio can be used to open an edit an XML file. If you drag and drop the hello.xml file over Microsoft Internet Explorer, you will be able to see the XML file as shown below. |
Problem 2 |
Using Microsoft Visual Studio open the hello.xml file, then edit the file to create an error in the closing tag as shown. Microsoft Visual Studio will indicate the error. |
Problem 3 |
Create an XML file called people.xml to store the name and personal information of your friends. You may create the file using Microsoft Visual Studio, Notepad or your favorite editor. |
Root Node |
An XML file is structured in nodes. The main node is called Root Node. In the people.xml file, the root node is the <people> node as shown below. |
Child Nodes |
The main node may have several child nodes. In the people.xml file, the <friend> nodes are child nodes of the root node <people> as shown below. |
Elements |
A node may have several elements. For instance, in the people.xml file the tags: first_name, last_name, age, email, phone and sex are elements of the friend node as shown below. |
Special Symbols |
As tags are defined using the symbols: > and <. These characters cannot be used for other purposes. XML has five reserved characters: >, < &, ' and ". In other to use these characters an special sequence must be used as shown. |
Special Symbol | Meaning |
> | > |
< | < |
& | & |
' | ' |
" | " |
Problem 4 |
Create an XML file called equation to display the equation shown. |
Comments |
XML allows introducing comments to an XML file to make the file easy to understand. As in other languages, comments provide information that is not obvious. Comments in HTML and XML use the same format. |
Problem 5 |
Edit the people.xml file to introduce some comments as shown. |
Attributes |
XML allows adding one or more attributes to each tag. An attribute is declared inside the tag as shown in the next problem. In this case, the Social Security Number (SSN) is an attribute of friend. In Mexico a RFC can be an attribute. Inside the University a student ID (NUA) can be an attribute. |
Tip |
Use attributes to identify a child node, and use node elements to include properties of the child node. Thus, an attribute identifies a child node, while an element provides more information about then node. |
Problem 6 |
Edit the people.xml file to add his or her Social Security Number. |
Including Text |
When including too much text into an XML file, the reserved characters must be replaced before pasting or writing the text. It is possible to paste a text block without replacing the reserved characters using a CDATA block as shown in the next problem. |
Problem 7 |
Create the file program.xml to include a block code as shown. |
Problem 8 |
Create a Dialog application called ReadingXml using Wintempla. Using Wintempla insert a textbox called tbxOutput. Set the multiline property of the textbox. |
Step A |
Open and edit the stdafx.h file of your project by including the msxml.h file as shown. |
stdafx.h |
// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // . . . #include "msxml.h" |
Step B |
Copy the people.xml file to the folder of your project. |
Step C |
Edit the ReadingXml.cpp file as shown. |
ReadingXml.cpp |
#include "stdafx.h" //________________________________________ ReadingXml.cpp #include "ReadingXml.h" int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE , LPTSTR cmdLine, int cmdShow){ ReadingXml app; return app.BeginDialog(IDI_READINGXML, hInstance); } void ReadingXml::Window_Open(Win::Event& e) { ::CoInitialize(NULL); try { VARIANT_BOOL ok(false); _variant_t fileName("people.xml"); //_____________________________________________________ Load the XML File: people.xml IXMLDOMDocumentPtr document; HRESULT hr = document.CreateInstance(__uuidof(DOMDocument)); if (FAILED(hr)) throw _com_error(hr); document->load(fileName, &ok); //_____________________________________________________ Get the List of Nodes (friend list) IXMLDOMNodeListPtr list; document->getElementsByTagName(_bstr_t(L"friend"), &list); //_____________________________________________________ Get Node Count long friendCount = 0; list->get_length(&friendCount); //_____________________________________________________ Travel node by node (Friend by Friend) list->reset(); IXMLDOMNodePtr node; IXMLDOMNodeListPtr children; IXMLDOMNodePtr child; DOMNodeType nodeType; long childrenCount = 0; _bstr_t text; for(long i = 0; i < friendCount; i++) { list->get_item(i, &node); //____________________________ Get Child Node List node->get_childNodes(&children); children->get_length(&childrenCount); for(long j = 0; j < childrenCount; j ++) { children->get_item(j, &child); child->get_nodeType(&nodeType); if (nodeType != NODE_ELEMENT) continue; child->get_text(&text.GetBSTR()); this->tbxOutput.Text += text.GetBSTR(); this->tbxOutput.Text += L"\r\n"; } this->tbxOutput.Text += L"_______________________\r\n"; } } catch(_com_error e) { this->MessageBox(e.ErrorMessage(), L"Using MS XML", MB_OK | MB_ICONERROR); } ::CoUninitialize(); } |
Problem 9 |
Work in groups of four student to discuss:(a) Which is it easier to implement in a program: Save or Load XML.(b) In the variable IXMLDOMDocumentPtr of the previous code, what is the meaning of the letter "I" located at the beginning?(c) In the variable IXMLDOMDocumentPtr of the previous code, what is the meaning of "DOM"?(d) In the variable IXMLDOMDocumentPtr of the previous code, what is the meaning of "Ptr" at the end of the variable? Trabaje en grupos de cuatro estudiantes para discutir:(a) Cuál es más fácil de implementar en un programa: Guardar o Cargar XML.(b) En la variable IXMLDOMDocumentPtr del código previo, Cuál es el significado de la letra "I" del principio?(c) En la variable IXMLDOMDocumentPtr del código previo, Cuál es el significado de "DOM"?(d) En la variable IXMLDOMDocumentPtr del código previo, Cuál es el significado de la "Ptr" de al final? |
Problem 10 |
Work in groups of four student to design a class to process XML. You must indicate:
Trabaje en grupos de cuatro estudiantes para diseñar una clase para procesar XML. Usted debe indicar:
|
Problem 11 |
Work in groups of four student to explain the Sys::Xml class of any Wintempla project. You must indicate:
Trabaje en grupos de cuatro estudiantes para explicar la clase Sys::Xml de cualquier proyecto de Wintempla. Usted debe indicar:
|
Problem 12 |
Wintempla provides the Sys::Xml class to create and read XML. Each node has a vector of Sys::Xml to store its children. Create a Wintempla Dialog application called EasyXml. Use Wintempla to insert a textbox called tbxOutput. Set the multiline property of the textbox. Copy the people.xml file to the folder project. Wintempla proporciona la clase Sys::Xml para crear y leer XML. Cada nodo tiene un vector de Sys::Xml para almacenar sus niños. Cree una aplicación de diálogo de Wintempla llamada EasyXml. Use Wintempla para inserta una caja de texto llamada tbxOutput. Fije la propiedad de multi-línea en la caja de texto. Copie el archivo people.xml en la carpeta del proyecto. |
EasyXml.h |
#pragma once //______________________________________ EasyXml.h #include "Resource.h" class EasyXml: public Win::Dialog { public: EasyXml() { } ~EasyXml() { } void DisplayNode(Sys::Xml& xmlNode); void DisplayNameAndValue(const wstring& name, const wstring& value); protected: ... }; |
EasyXml.cpp |
... void EasyXml::Window_Open(Win::Event& e) { Sys::Xml root; const wchar_t* error = root.Load(L"people.xml"); if (error != NULL) { this->MessageBox(error, L"EasyXml", MB_OK | MB_ICONERROR); return; } DisplayNode(root); } void EasyXml::DisplayNode(Sys::Xml& xmlNode) { DisplayNameAndValue(xmlNode.name, xmlNode.value); tbxOutput.Text += L"\r\n"; //____________________________________________ Attributes if (xmlNode.attribute.empty() == false) { tbxOutput.Text += L"*ATTRIBUTES OF "; tbxOutput.Text += xmlNode.name; tbxOutput.Text += L"\r\n"; map<wstring, wstring>::iterator attb = xmlNode.attribute.begin(); const map<wstring, wstring>::iterator aend = xmlNode.attribute.end(); for( ; attb != aend; attb++) { DisplayNameAndValue(attb->first, attb->second); tbxOutput.Text += L"\r\n"; } } //____________________________________________ Children if (xmlNode.child.empty() == false) { tbxOutput.Text += L"*CHILDREN OF "; tbxOutput.Text += xmlNode.name; tbxOutput.Text += L"\r\n"; list<Sys::Xml>::iterator child_node; const list<Sys::Xml>::iterator last_child = xmlNode.child.end(); for (child_node = xmlNode.child.begin(); child_node != last_child; child_node++) { DisplayNode(*child_node); } } } void EasyXml::DisplayNameAndValue(const wstring& name, const wstring& value) { if (name.empty() == true) return; tbxOutput.Text += name; if (value.empty() == false) { tbxOutput.Text += L"="; tbxOutput.Text += value; } } |
Problem 13 |
Repeat the previous problem using Java. In Java, it is possible to parse XML using: the Document Object Model (DOM), or using SAX. In both cases, you need to have installed the Java API for XML (JAXP). In the example below, we will use SAX. To use SAX you need to create a class derived from DefaultHandler that implements functions, in this case we will override: startElement, endElement, and characters. Repita el problema anterior usando Java. En Java, es posible convertir texto a XML usando: El Modelo del Objeto del Documento DOM, o usando SAX. En ambos casos, usted necesita tener instalado la API de Java para XML (JAXP.) En el ejemplo de abajo usaremos SAX. Para usar SAX usted necesita crear una clase derivada de DefaultHandler que implemente algunas funciones, en este caso nosotros sobrecargaremos: startElement, endElement, y characters. |
XmlHandler.java |
import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.SAXException; import org.xml.sax.Attributes; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class XmlHandler extends org.xml.sax.helpers.DefaultHandler { public String output = null; public XmlHandler() { output = ""; } public void startElement(String namespaceUri, String localName, String qualifiedName, Attributes attributes) throws SAXException { output += "_______________ Begin of "; output += qualifiedName; output += "\r\n"; final int numAttributes = attributes.getLength(); int i; for (i = 0; i < numAttributes; i++) { output += attributes.getValue(i).toString(); output += "\r\n"; } } public void endElement(String namespaceUri, String localName, String qualifiedName) throws SAXException { output += "_______________ End of "; output += qualifiedName; output += "\r\n"; } public void characters(char[] chars, int startIndex, int endIndex) throws SAXException { String data = new String(chars, startIndex, endIndex); output += data; output += "\r\n"; } } |
EasyXmlJ.java |
import org.xml.sax.Attributes; //import jdk.internal.org.xml.sax.Attributes; import org.xml.sax.SAXException; // import jdk.internal.org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.*; public class EasyXmlJ extends JFrame { private JTextArea tbxOutput; public EasyXmlJ() { this.setTitle("EasyXmlJ"); this.setSize(600, 900); this.addWindowListener(new ExitListener()); //_________________________________________________________________________ Create GUI Container pane = this.getContentPane(); pane.setLayout(new FlowLayout()); tbxOutput = new JTextArea(30, 70); pane.add(tbxOutput); //_______________________________________________________________________ Parse the file content XmlHandler xmlHandler = new XmlHandler(); SAXParserFactory factory = SAXParserFactory.newInstance(); try { File file = new File("C:\\selo\\vs\\CreateHelp\\Help\\02Wintempla\\24XML\\00XML\\EasyXmlJ\\people.xml"); SAXParser parser = factory.newSAXParser(); parser.parse(file, xmlHandler); tbxOutput.append(xmlHandler.output); } catch (Exception e) { tbxOutput.append(e.toString()); tbxOutput.append("\r\n"); } } public static void main(String[] args) { EasyXmlJ frame = new EasyXmlJ(); frame.pack(); frame.setVisible(true); } public class ExitListener extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } } |
Problem 14 |
Repeat the previous problem using Android. Edit the activity_main.xml file to have a TextView called tbxOutput. Call your project EasyXmlA. Repita el problema anterior usando Android. Edite el archivo activity_mail.xml para tener una TextView llamada tbxOutput. Llame a su proyecto EasyXmlA. |
Step A |
Add a new class called XmlHandler as shown. Edit the file as shown (this file is the same as the Java application). Agregue una clase nueva llamada XmlHandler como se muestra. Edite el archivo como se muestra (este archivo es el mismo que el de la aplicación de Java). |
Step B |
Edit the MainActivity.java file as shown. Edite el archivo MainActivity.java como se muestra. |
MainActivity.java |
package com.selo.easyxmla; import android.app.Activity; import android.os.Build; import android.os.Bundle; import android.widget.TextView; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.nio.charset.StandardCharsets; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tbxOutput = (TextView)findViewById(R.id.tbxOutput); //_______________________________________________________________________ Parse the file content XmlHandler xmlHandler = new XmlHandler(); SAXParserFactory factory = SAXParserFactory.newInstance(); try { SAXParser parser = factory.newSAXParser(); InputStream inputStream = new ByteArrayInputStream(GetXml().getBytes(StandardCharsets.UTF_8)); parser.parse(inputStream, xmlHandler); tbxOutput.append(xmlHandler.output); } catch (Exception e) { tbxOutput.append(e.toString()); tbxOutput.append("\r\n"); } } public String GetXml() { String output = ""; output += "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"; output += "<people>\r\n"; output += "<friend ssn=\"455-45-3434\">\r\n"; output += "<first_name>Mary</first_name>\r\n"; output += "<last_name>Smith</last_name>\r\n"; output += "<age>20</age>\r\n"; output += "<email>mary@yahoo.com</email>\r\n"; output += "<!-- This is her home number as she does not have a cell yet -->\r\n"; output += "<phone>415-456-8945</phone>\r\n"; output += "<sex>female</sex>\r\n"; output += "</friend>\r\n"; output += "<friend ssn=\"556-22-3446\">\r\n"; output += "<first_name>Peter</first_name>\r\n"; output += "<last_name>Ferry</last_name>\r\n"; output += "<age>22</age>\r\n"; output += "<email>peter@live.com</email>\r\n"; output += "<phone>212-356-4545</phone>\r\n"; output += "<sex>male</sex>\r\n"; output += "</friend>\r\n"; output += "<friend ssn=\"877-77-3999\">\r\n"; output += "<first_name>Jim</first_name>\r\n"; output += "<last_name>Tore</last_name>\r\n"; output += "<age>17</age>\r\n"; output += "<email>jimmy@live.com</email>\r\n"; output += "<phone>210-153-8422</phone>\r\n"; output += "<sex>male</sex>\r\n"; output += "</friend>\r\n"; output += "</people>\r\n"; return output; } } |
Problem 15 |
Create a Dialog application called ClientXml using Wintempla to create an XML object. Cree una aplicación de diálogo llamada ClientXml usando Wintempla para crear un objeto de XML. |
ClientXml.cpp |
... void ClientXml::Window_Open(Win::Event& e) { Sys::Xml xml; xml.name = L"clients"; //________________________________________ Client 0 Sys::Xml& client0 = xml.AddChild(L"client"); client0.AddChild(L"name", L"John Smith"); client0.AddChild(L"age", L"22"); //________________________________________ Client 1 Sys::Xml& client1 = xml.AddChild(L"client"); client1.AddChild(L"name", L"Mary Miller"); client1.AddChild(L"age", L"44"); // wstring text; xml.GetXmlText(text); this->tbxOutput.Text = text; } |
Problem 16 |
Repeat the previous problem using Java. We will create the class called XmlWritter to ease the creation of XML. Repita el problema anterior usando Java. Nosotros crearemos la clase llamada XmlWriter para facilitar la creación de XML. |
XmlWriter.java |
public class XmlWriter { private boolean isUtf8 = true; public int indentationLevel = 0; public String content = ""; private String rootNodeName = "root"; public XmlWriter(boolean isUtf8, String rootNodeName) { this.isUtf8 = isUtf8; this.rootNodeName = rootNodeName; indentationLevel = 0; if (isUtf8 == true) { content = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"; } else { content = "<?xml version=\"1.0\"?>\r\n"; } content += "<"; content += rootNodeName; content += ">\r\n"; indentationLevel++; } public String getContent() { // Use isUtf8 to return the proper content encoding (UTF-8 o UTF-16) String output = content; output += "</"; output += rootNodeName; output += ">\r\n"; indentationLevel--; return output; } public void childBegin(String childName) { indentation(); content += "<"; content += childName; content += ">\r\n"; indentationLevel++; } public void childEnd(String childName) { indentationLevel--; indentation(); content += "</"; content += childName; content += ">\r\n"; } public void element(String name, String value) { indentation(); content += "<"; content += name; content += ">"; content += ToXml(value); content += "</"; content += name; content += ">\n"; } public void indentation() { int i; for(i = 0; i < indentationLevel; i++) { content += " "; } } public static String ToXml(String input) { final int len = input.length(); if (len == 0) return ""; String output =""; int i; for(i = 0; i < len; i++) { switch(input.charAt(i)) { ... } } return output; } } |
ClientXmlJ.java |
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ClientXmlJ extends JFrame { private JTextArea tbxOutput; public ClientXmlJ() { this.setTitle("ClientXmlJ"); this.setSize(600, 900); this.addWindowListener(new ExitListener()); //________________________________ Create GUI Container pane = this.getContentPane(); pane.setLayout(new FlowLayout()); tbxOutput = new JTextArea(30, 70); pane.add(tbxOutput); //_____________________________________ XML XmlWriter xw = new XmlWriter(true, "clients"); //________________________________________ Client 0 xw.childBegin("client"); xw.element("name", "John Smith"); xw.element("age", "22"); xw.childEnd("client"); //________________________________________ Client 1 xw.childBegin("client"); xw.element("name", "Mary Miller"); xw.element("age", "44"); xw.childEnd("client"); // tbxOutput.setText(xw.getContent()); } public static void main(String[] args) { ClientXmlJ frame = new ClientXmlJ(); frame.pack(); frame.setVisible(true); } public class ExitListener extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } } |
Problem 17 |
Repeat the previous problem using Android. Insert a TextView called tbxOutput to display the output of the program. Use the XmlWriter class created in the previous problem. Call your proyect Repita el problema anterior usando Android. Inserte un TextView llamado tbxOutput para mostrar la salida de su programa. Use la clase XmlWriter creada en el problema previo. |
MainActivity.java |
package com.selo.clientxmla; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tbxOutput = (TextView)findViewById(R.id.tbxOutput); //_____________________________________ XML XmlWriter xw = new XmlWriter(true, "clients"); //________________________________________ Client 0 xw.childBegin("client"); xw.element("name", "John Smith"); xw.element("age", "22"); xw.childEnd("client"); //________________________________________ Client 1 xw.childBegin("client"); xw.element("name", "Mary Miller"); xw.element("age", "44"); xw.childEnd("client"); // tbxOutput.setText(xw.getContent()); } } |
Tip |
Wintempla provides the following functions to manipulate XML:
Wintempla proporciona las siguientes funciones para manipular XML:
|
Problem 18 |
Create a Dialog application called ClientSql using Wintempla to move data from:
The application displays client information from the database best_buy described in Wintempla > Information System > Sharing . Cree una aplicación de diálogo llamada ClientSql usando Wintempla para mover datos desde:
La aplicación muestra la información de los clientes de la base de datos best_buy descrita en Wintempla > Information System > Sharing. |
stdafx.h |
... #define CONNECTION_STRING L"DRIVER={SQL Server};server=localhost\\SQLEXPRESS;database=best_buy;Trusted_Connection=yes" |
ClientSql.cpp |
... void ClientSql::Window_Open(Win::Event& e) { //______________________________________________________ 1. From SQL to XML Sql::SqlConnection conn; Sys::Xml xml; xml.name = L"client_list"; //root Sys::Xml& client = xml.AddChild(L"client"); client.AddChild(L"client_id"); client.AddChild(L"last_name"); client.AddChild(L"first_name"); client.AddChild(L"city"); client.AddChild(L"birthdate"); try { //conn.OpenSession(DSN, USERNAME, PASSWORD); //Control Panel>Administrative Tools>Data Sources (ODBC)>Create dsn_myDatabase conn.OpenSession(hWnd, CONNECTION_STRING); conn.ExecuteSelect(L"SELECT client_id, last_name, first_name, city, birthdate FROM client", 100, xml); } catch (Sql::SqlException e) { this->MessageBox(e.GetDescription(), L"Error", MB_OK | MB_ICONERROR); } wstring text; xml.GetXmlText(text); this->MessageBox(text, L"ClientSql", MB_OK | MB_ICONINFORMATION); //__________________________________________________ 2. From XML to ListView lvClient.ImportFromXml(false, xml); } |
Tip |
XML can be used to perform transactions among computers running different platforms. DTD files and schemas files are used to check that the information received during a transaction is valid. |
Problem 19 |
Modify the previous problem by adding a button to export to XML the content of the List View control. Modifique el problema previo agregando un botón para exportar a XML el contenido del control de ListView. |
ClientSql.cpp |
... bool ClientSql::ExportToXml(Win::ListView& inputListView, const wchar_t* filename) { int i, j; //___________________________________________ 1. Get Column Information const int colCount = inputListView.GetColumnCount(); vector<wstring> colName; ... for (...) { inputListView.GetColumnText(i, colName[i]); } //___________________________________________ 2. XML Head wstring file_content; ... //__________________________________________ 3. Render each item const int rowCount = inputListView.GetItemCount(); wstring item_text; ... for (i = 0; i < rowCount; i++) { file_content += ...; for (j = 0; j < colCount; j++) { ... } ... } ... //___________________________________________ 4. Convert to UTF-8 string utf8_text; Sys::Convert::WstringToUTF8(file_content, utf8_text); //___________________________________________ Save Sys::File file; if (file.CreateForWritting(filename) == false) return false; return file.WriteText(utf8_text); } void ClientSql::btExportToXml_Click(Win::Event& e) { Win::FileDlg dlg; dlg.Clear(); dlg.SetFilter(L"XMLfiles (*.xml)\0*.xml\0\0", 0, L"xml"); if (dlg.BeginDialog(hWnd, L"Save XML", true) == TRUE) { if (ExportToXml(lvClient, dlg.GetFileNameFullPath()) == false) { this->MessageBox(L"Unable to save", L"ClientSql", MB_OK | MB_ICONERROR); } } } |
Problem 20 |
Create a program called XmlList with a textbox (multiline and with a vertical scroll bar) and an Open button. When the user clicks the Open button, the user can select an XML file to show the tokens of the file. Create the XmlTokenizer class to promote Object-Oriented Programming. To test your program, use the people.xml file without SSN. Cree un programa llamado XmlList con una caja de texto (multilínea y con una barra de desplazamiento vertical) y un botón de Abrir. Cuando el usuario hace clic en el botón de abrir, el usuario puede seleccionar un archivo de XML para mostrar los tokens del archivo. Cree la clase XmlTokenizer para promover el uso de la Programación Orientada a Objetos. Para probar su programa, use el archivo people.xml sin el SSN. |
XmlList.h |
#pragma once //______________________________________ XmlList.h #include "Resource.h" #include "XmlTokenizer.h" class XmlList: public Win::Dialog ... |
XmlList.cpp |
... void XmlList::btOpen_Click(Win::Event& e) { void XmlList::btOpen_Click(Win::Event& e) { Win::FileDlg dlg; dlg.SetFilter(L"XML files (*.xml)\0*.xml\0\0", 0, L"xml"); if (dlg.BeginDialog(hWnd, L"Open XML", false) != TRUE) return; XmlTokenizer tokenizer; list<wstring> token; if (tokenizer.ImportXml(dlg.GetFileNameFullPath(), token) == false) { this->MessageBox(L"Unable to import", L"XmlViewer", MB_OK | MB_ICONERROR); } //_______________________________________ Display tokens in textbox list<wstring>::iterator p; wstring text; for (p = token.begin(); p != token.end(); p++) { text += *p; text += L"\r\n"; } tbxOutput.Text = text; } |
XmlTokenizer.h |
#pragma once #pragma once class XmlTokenizer { public: XmlTokenizer(); ~XmlTokenizer(); bool ImportXml(const wchar_t* filename, list<wstring>& out_token); private: const wchar_t* p; void Tag(list<wstring>& out_token); bool IsEmpty(const wstring& token); }; |
XmlTokenizer.cpp |
#include "stdafx.h" #include "XmlTokenizer.h" XmlTokenizer::XmlTokenizer() { } XmlTokenizer::~XmlTokenizer() { } bool XmlTokenizer::ImportXml(const wchar_t* filename, list<wstring>& out_token) { //___________________________________________ 1. file > utf8_text wstring file_content; if (Sys::FileAssistant::TextUtf8Load(filename, file_content) == false) return false; //___________________________________________2. Process each tag wstring token; for (p = file_content.c_str(); *p != L'\0'; p++) { ... } return true; } void XmlTokenizer::Tag(list<wstring>& out_token) { p++; // move after < wstring token; for (; p != L'\0'; p++) { if (*p == '>') //____________________________________ End of tag { ... } else if (*p == '/' || *p == '=' || *p == '?') //__________________ Special Characters { ... } else if (*p == '\"') //________________________________ "value" { ... } else if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') //______________ Spaces, Tabs, Line Breaks or Carriage Returns { ... } else { ... } } } // An empty string has only tabs, spaces, line breaks or carriage returns bool XmlTokenizer::IsEmpty(const wstring& token) { if (token.empty() == true) return true; wstring::const_iterator p; for (p = token.begin(); p != token.end(); p++) { if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') continue; return false; } return true; } |
Problem 21 |
Create a program called XmlViewer with a ListView control and an Open button. When the user clicks the Open button, the user can select an XML file to show the content of the file in the List View control. Create the XmlReader class to promote Object-Oriented Programming. Use the XmlTokenier class of the previous problem. Cree un programa llamado XmlViewer con un control de ListView y un botón de Abrir. Cuando el usuario hace clic en el botón de abrir, el usuario puede seleccionar un archivo de XML para mostrar el contenido del archivo en el control de ListView. Cree la clase XmlReader para promover el uso de la Programación Orientada a Objetos. Use la clase XmlTokenizer del problema previo. |
XmlViewer.h |
#pragma once //______________________________________ XmlViewer.h #include "Resource.h" #include "XmlReader.h" ... |
XmlViewer.cpp |
... void XmlViewer::Window_Open(Win::Event& e) { } void XmlViewer::btOpen_Click(Win::Event& e) { Win::FileDlg dlg; dlg.Clear(); dlg.SetFilter(L"XML files (*.xml)\0*.xml\0\0", 0, L"xml"); if (dlg.BeginDialog(hWnd, L"Open XML", false) == TRUE) { XmlReader reader; if (reader.ImportXml(dlg.GetFileNameFullPath(), lvOutput) == false) { this->MessageBox(L"Unable to import", L"XmlViewer", MB_OK | MB_ICONERROR); } } } |
XmlReader.h |
#pragma once #include "XmlTokenizer.h" class XmlReader { public: XmlReader(); ~XmlReader(); bool ImportXml(const wchar_t* filename, Win::ListView& outputListView); private: list<wstring> token; list<wstring>::iterator position; // <?xml version="1.0" encoding="utf-8"?> bool ReadXmlHeader(); bool ReadChildNode(Win::ListView& outputListView); // Read <item> and out_tagname will be "item" bool ReadTag(wstring& out_tagname); // Read </item> and out_tagname will be "item" bool ReadTagEnd(wstring& out_tagname); bool ReadElements(const wstring& child_name, Win::ListView& outputListView); }; |
XmlReader.cpp |
... bool XmlReader::ImportXml(const wchar_t* filename, Win::ListView& outputListView) { XmlTokenizer xmlTokenizer; if (xmlTokenizer.ImportXml(filename, token) == false) return false; position = token.begin(); //___________________________________________ 1. Read XML Header <?xml version="1.0" encoding="utf-8"?> if (ReadXmlHeader() == false) return false; //___________________________________________ 2. Read Root Node <list> wstring root_begin; if (ReadTag(root_begin) == false) return false; //___________________________________________ 3. Read Child Nodes list<wstring>::iterator prev; while (position != token.end()) { ReadChildNode(outputListView); //___________________________ End of Children? prev = position; if (*position == L"<") { position++; if (position != token.end()) { if (*position == L"/") { position = prev; // Move back break; } } } position = prev; // Move back } //___________________________________________ 4. Read Root Node End wstring root_end; if (ReadTagEnd(root_end) == false) return false; return (root_begin == root_end); } bool XmlReader::ReadXmlHeader() { //_____________________________________ < if (*position != L"<") return false; position++; if (position == token.end()) return false; ... return true; } bool XmlReader::ReadTag(wstring& out_tagname) { ... } bool XmlReader::ReadTagEnd(wstring& out_tagname) { ... } bool XmlReader::ReadChildNode(Win::ListView& outputListView) { //______________________________________________ 1. <item> wstring child_name; if (ReadTag(child_name) == false) return false; //______________________________________________ 2. Read Elements ReadElements(child_name, outputListView); //______________________________________________ 3. </item> wstring child_end_name; if (ReadTagEnd(child_end_name) == false) return false; return (child_name == child_end_name); } bool XmlReader::ReadElements(const wstring& child_name, Win::ListView& outputListView) { wstring element_name; wstring element_end_name; vector<wstring> column_names; vector<wstring> values; list<wstring>::iterator prev; while (position != token.end()) { //__________________________________________________ End of Child? ... //_______________________________________________ <last_name> if (ReadTag(element_name) == false) return false; //_______________________________________________ Smith values.push_back(*position); position++; if (position == token.end()) return false; //_______________________________________________ </last_name> if (ReadTagEnd(element_end_name) == false) return false; if (element_name != element_end_name) return false; // if (outputListView.GetColumnCount() == 0) { column_names.push_back(element_name); } } return false; } |