我必须读取一个名为“ address.xml”的文件,其中包含:
<?xml version="1.0"?>
<address_book>
<contact>
<name>George Clooney</name>
<street>1042 El Camino Real</street>
<city>Beverly Hills</city>
<state>CA</state>
<zip>90214</zip>
</contact>
等等,具有多个联系人。只需要显示Palmdale城市的人。我已经定义了联系人的每个元素,但是当我尝试在Palmdale中显示联系人时,它仅列出一个联系人(文本文档中的最后一个)。我需要使用循环来显示所有这些内容吗?
void test2() {
ifstream fin;
string row, name, street, city, state, zip;
int start, end;
fin.open("address.xml");
if (fin.fail()) {
cout << "There was an error opening the file...";
exit(1);
}
while (getline(fin, row)) {
if ((start = row.find("<name>")) != string::npos) {
start = row.find(">");
end = row.find("</name>");
name = row.substr(start + 1, end - start - 1);
}
if ((start = row.find("<street>")) != string::npos) {
start = row.find(">");
end = row.find("</street>");
street = row.substr(start + 1, end - start - 1);
}
if ((start = row.find("<city>")) != string::npos) {
start = row.find(">");
end = row.find("</city>");
city = row.substr(start + 1, end - start - 1);
}
if ((start = row.find("<state>")) != string::npos) {
start = row.find(">");
end = row.find("</state>");
state = row.substr(start + 1, end - start - 1);
}
if ((start = row.find("<zip>")) != string::npos) {
start = row.find(">");
end = row.find("</zip>");
zip = row.substr(start + 1, end - start - 1);
}
}
if (city == "Palmdale") {
cout << name << endl << street << endl
<< city << endl << state << endl << zip << endl;
}
fin.close();
}
感谢所有可以指出正确方向的人
答案 0 :(得分:2)
您的if (city == "Palmdale") {...}
不在任何循环中,因此在处理完所有数据之后,它将仅运行一次。相反,您应该在每次获取所有数据时运行它。例如,如果您确定自己的模式将完全保持这种方式,则可以假设您在读取<zip>
元素时记录是完整的。或者更好的是,当<contact>
元素关闭时。试试这个:
while (getline(fin, row)) {
if ((start = row.find("<name>")) != string::npos) {
start = row.find(">");
end = row.find("</name>");
name = row.substr(start + 1, end - start - 1);
}
if ((start = row.find("<street>")) != string::npos) {
start = row.find(">");
end = row.find("</street>");
street = row.substr(start + 1, end - start - 1);
}
if ((start = row.find("<city>")) != string::npos) {
start = row.find(">");
end = row.find("</city>");
city = row.substr(start + 1, end - start - 1);
}
if ((start = row.find("<state>")) != string::npos) {
start = row.find(">");
end = row.find("</state>");
state = row.substr(start + 1, end - start - 1);
}
if ((start = row.find("<zip>")) != string::npos) {
start = row.find(">");
end = row.find("</zip>");
zip = row.substr(start + 1, end - start - 1);
}
if ((row.find("</contact>")) != string::npos) {
if (city == "Palmdale") {
cout << name << endl << street << endl
<< city << endl << state << endl << zip << endl;
}
}
}
fin.close();
}
如果它变得比这更复杂,我真的建议您使用XML库。实际上,如果您需要重做,我已经使用了一个。
例如,这就是使用tinyxml的样子(您所要做的就是将tinyxml2.h
和tinyxml2.cpp
添加到项目中):
#include <iostream>
#include <string>
#include "tinyxml2.h"
#include "tinyxml2.cpp"
int main() {
tinyxml2::XMLDocument doc;
doc.LoadFile("address.xml");
tinyxml2::XMLElement* book = doc.FirstChildElement("address_book");
for (tinyxml2::XMLElement* contact = book->FirstChildElement("contact");
contact != NULL; contact = contact->NextSiblingElement())
{
std::string name = contact->FirstChildElement("name")->GetText();
std::string street = contact->FirstChildElement("street")->GetText();
std::string city = contact->FirstChildElement("city")->GetText();
std::string state = contact->FirstChildElement("state")->GetText();
std::string zip = contact->FirstChildElement("zip")->GetText();
if (city == "Palmdale") {
std::cout << name << std::endl << street << std::endl
<< city << std::endl << state << std::endl << zip << std::endl;
}
}
}
注意:我不隶属于tinyxml,但过去曾使用过它。
答案 1 :(得分:1)
if (city == "Palmdale") {...}
仅适用于最后一条记录。您需要在循环内打印。 contact
节点,例如,如果从一个元素中省略城市,它将使用前一个元素的城市。