Harrix Блог

  • Списки статей
    • Все статьи
    • IT
    • Qt
    • C++
    • Сложение двух чисел
    • Web программированиe
    • FAQ
    • Latex
    • Установка программ
    • Мифы
    • Видео
    • Про фото
  • Проекты
  • Harrix.org
  • RSS
  • Контакты

Разбор XML файла с применением классов на C++/CLI

Продолжение разбора XML файла.

26.09.2016 Leave a Comment 4 609 просмотров

Продолжаем статью Пример разбора XML файла в Visual Studio 2015 на C++.

В статье не будет особо комментариев и подробностей ввиду определенных причин.

Содержание

  • XML файл
  • Постановка задачи
  • Интерфейс программы
  • Классы
  • Подготовка формы
  • Коды кнопок
  • Запуск приложения

XML файл

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8" ?>
<points name="Example">
    <point type="circle">
        <x>2</x>
        <y>3</y>
<name>Point 1</name>
    </point>
    <point type="circle">
        <x>1</x>
        <y>5</y>
<name>Point of cat</name>
    </point>
    <point type="square">
        <x>12</x>
        <y>-3</y>
<name>Point 3</name>
    </point>
</points>

Постановка задачи

У нас должно быть три класса.

  1. Абстрактный класс, описывающий точку в двумерном пространстве.
  2. Более расширенный класс, который описывает точку с именем и типом.
  3. Класс, содержащий массив точек, которые считываются из XML файла.

Также кроме загрузки файла, мы должны иметь возможность обработать данные, например, отфильтровать их.

Писать будем в Visual Studio 2015 под С++/CLI приложение CLR.

Интерфейс программы

2016-09-26_010419

Классы

Point.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#pragma once
 
using namespace System;
 
ref class Point {
public:
Point();
Point(int x, int y);
void setX(int x);
int getX();
void setY(int x);
int getY();
virtual String^ getInfo() = 0;
protected:
int x;
int y;
};
 
Point::Point() {
x = 0;
y = 0;
}
 
Point::Point(int x, int y) {
this->x = x;
this->y = y;
}
 
void Point::setX(int x) {
this->x = x;
}
 
int Point::getX() {
return x;
}
 
void Point::setY(int y) {
this->y = y;
}
 
int Point::getY() {
return y;
}

PointWithName.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#pragma once
 
#include "Point.h"
 
using namespace System;
 
ref class PointWithName: Point {
public:
PointWithName();
PointWithName(int x, int y);
String^ getInfo() override;
String^ getName();
void setName(String^ name);
String^ getType();
void setType(String^ name);
protected:
String^ type;
String^ name;
};
 
PointWithName::PointWithName() {
x = 0;
y = 0;
}
 
PointWithName::PointWithName(int x, int y) {
this->x = x;
this->y = y;
}
String^ PointWithName::getInfo() {
String^ text;
 
text += "Name = " + name + "\r\n";
text += "Type = " + type + "\r\n";
text += "(" + Convert::ToString(x) + "; " + Convert::ToString(y) + ")\r\n";
 
return text;
}
 
String^ PointWithName::getName() {
return name;
}
 
void PointWithName::setName(String^ name) {
this->name = name;
}
 
String^ PointWithName::getType() {
return type;
}
 
void PointWithName::setType(String^ type) {
this->type = type;
}

Points.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#pragma once
 
#include "PointWithName.h"
#include <cliext/vector>
 
using namespace System;
using namespace System::Xml;
using namespace cliext;
 
ref class Points {
public:
Points ();
Points (String^ fileName);
int size ();
void setFileName(String^ fileName);
PointWithName^ getElement(int i);
String^ getInfo ();
String^ getInfoWithFilterByX (int filter);
String^ getInfoWithFilterByName(String^ filter);
private:
vector<PointWithName^>^ vectorPoints;
void readXML(String^ fileName);
};
 
Points::Points() {
vectorPoints = gcnew vector<PointWithName^>();
}
 
Points::Points(String^ fileName) {
vectorPoints = gcnew vector<PointWithName^>();
 
readXML(fileName);
}
 
void Points::setFileName(String^ fileName) {
vectorPoints->clear();
 
readXML(fileName);
}
 
void Points::readXML(String^ fileName) {
PointWithName^ temp;
 
XmlTextReader reader(fileName);
 
while (reader.ReadToFollowing("points")) {
int pointCount = 0;
 
if (reader.ReadToDescendant("point")) {
do {
pointCount++;
 
int x, y;
String^ type;
String^ name;
 
type = reader.GetAttribute("type");
 
XmlReader^ inner = reader.ReadSubtree();
 
while (inner->Read()) {
if ((inner->Name == "x") && (inner->NodeType == XmlNodeType::Element)) {
inner->Read();
x = Convert::ToInt32(inner->Value);
}
if ((inner->Name == "y") && (inner->NodeType == XmlNodeType::Element)) {
inner->Read();
y = Convert::ToInt32(inner->Value);
}
if ((inner->Name == "name") && (inner->NodeType == XmlNodeType::Element)) {
inner->Read();
name = inner->Value;
}
}
 
temp = gcnew PointWithName(x, y);
temp->setType(type);
temp->setName(name);
 
vectorPoints->push_back(temp);
 
} while (reader.ReadToNextSibling("point"));
}
}
}
 
int Points::size() {
return vectorPoints->size();
}
 
PointWithName^ Points::getElement(int i) {
return vectorPoints->at(i);
}
 
String^ Points::getInfo() {
String^ info;
 
for (int i = 0; i < vectorPoints->size(); i++) {
info += "Name = " + vectorPoints->at(i)->getName() + "\r\n";
info += "Type = " + vectorPoints->at(i)->getType() + "\r\n";
info += "(" + vectorPoints->at(i)->getX() + "; " + vectorPoints->at(i)->getY() + ")\r\n\r\n";
}
 
return info;
}
 
String^ Points::getInfoWithFilterByX(int filter) {
String^ info;
 
if (vectorPoints->size() == 0)
return "File is not loaded\r\n";
 
int findCount = 0;
for (int i = 0; i < vectorPoints->size(); i++) {
if (vectorPoints->at(i)->getX() == filter) {
info += "Name = " + vectorPoints->at(i)->getName() + "\r\n";
info += "Type = " + vectorPoints->at(i)->getType() + "\r\n";
info += "(" + vectorPoints->at(i)->getX() + "; " + vectorPoints->at(i)->getY() + ")\r\n\r\n";
findCount++;
}
}
 
if (findCount == 0)
info += "Such points are not found\r\n";
 
return info;
}
 
String^ Points::getInfoWithFilterByName(String^ filter) {
String^ info;
 
if (vectorPoints->size() == 0)
return "File is not loaded\r\n";
 
int findCount = 0;
for (int i = 0; i < vectorPoints->size(); i++) {
if (vectorPoints->at(i)->getName()->IndexOf(filter) >= 0) {
info += "Name = " + vectorPoints->at(i)->getName() + "\r\n";
info += "Type = " + vectorPoints->at(i)->getType() + "\r\n";
info += "(" + vectorPoints->at(i)->getX() + "; " + vectorPoints->at(i)->getY() + ")\r\n\r\n";
findCount++;
}
}
 
if (findCount == 0)
info += "Such points are not found\r\n";
 
return info;
}

Подготовка формы

В файле формы (у меня это MyForm.h) подключите файл третьего класса.

1
#include "Points.h"

А в переменных формы добавьте указатель на класс Points.

1
Points^ pointsFromXML;

2016-09-26_011048

Коды кнопок

Кнопка Load XML.

1
2
3
4
5
6
7
8
9
10
if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK) {
textBox2->Clear();
String^ fileName = openFileDialog1->FileName;
 
pointsFromXML = gcnew Points(fileName);
 
textBox2->Text += "Amount of points = ";
textBox2->Text += Convert::ToString(pointsFromXML->size()) + "\r\n";
textBox2->Text += pointsFromXML->getInfo() + "\r\n";
}

Кнопка Filter by x.

1
2
3
4
5
6
7
8
9
if (pointsFromXML != nullptr) {
textBox2->Clear();
int filter = 0;
Int32::TryParse(textBox1->Text, filter);
 
textBox2->Text += pointsFromXML->getInfoWithFilterByX(filter);
}
else
textBox2->Text = "File is not loaded\r\n";

Кнопка Filter by name.

1
2
3
4
5
6
7
8
if (pointsFromXML != nullptr) {
textBox2->Clear();
String^ filter = textBox3->Text;
 
textBox2->Text += pointsFromXML->getInfoWithFilterByName(filter);
}
else
textBox2->Text = "File is not loaded\r\n";

Кнопка All info.

1
2
3
4
5
6
7
8
9
if (pointsFromXML != nullptr) {
textBox2->Clear();
 
textBox2->Text += "Amount of points = ";
textBox2->Text += Convert::ToString(pointsFromXML->size()) + "\r\n";
textBox2->Text += pointsFromXML->getInfo() + "\r\n";
}
else
textBox2->Text = "File is not loaded\r\n";

Запуск приложения

При запуске приложения и открытии XML файла мы можем получать информацию по точкам или их фильтровать.

2016-09-26_011714


Статьи по теме:

  1. Пример разбора XML файла в Visual Studio 2015 на C++
  2. Создание класса с вектором экземпляров другого класса на C++/CLI
  3. Подключение SQLite в проектах Visual Studio в CRL проекте
  4. Вывод таблицы вручную в Visual Studio в CLR приложении

IT C++, C++/CLI, Visual Studio, XML

© 2014 Harrix