我的XML文件有:
<套餐> xmlMetadata < / Package>
我正在此文件中搜索标记,并且必须在控制台上打印此标记的开始和结束标记之间的文本。即在这种情况下,我希望在控制台上打印xmlMetadata。类似地,它应该在文件中更进一步,如果它遇到另一个<套餐>标记在同一个文件中。
这是我的代码,但是它正在打印整个文件的内容:
{
string line="< Package >";
ifstream myfile (xmlFileName); //xmlFileName is xml file in which search is to done
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
std::cout<<line<< endl;
}
myfile.close();
}
else cout << "Unable to open file";
}
在我的整个xml下面显示:
< ? xml version="1.0" ? >
< fileStructure >
< Main_Package >
File_Navigate
< /Main_Package >
< Dependency_Details >
< Dependency >
< Package >
xmlMetadata
< /Package >
< Header >
xmlMetadata.h
< /Header >
< Header_path >
C:\Dependency\xmlMetadata\xmlMetadata.h
< /Header_path >
< Implementation >
xmlMetadata.cpp
< /Implementation >
< Implementation_path >
C:\Dependency\xmlMetadata\xmlMetadata.cpp
< /Implementation_path >
< /Dependency >
< Dependency >
< Package >
xmlMetadata1
< /Package >
< Header >
xmlMetadata1.h
< /Header >
< Header_path >
C:\Dependency\xmlMetadata\xmlMetadata1.h
< /Header_path >
< Implementation >
xmlMetadata1.cpp
< /Implementation >
< Implementation_path >
C:\Dependency\xmlMetadata\xmlMetadata1.cpp
< /Implementation_path >
< /Dependency >
< /Dependency_Details >
< /fileStructure >
答案 0 :(得分:6)
Getline不会搜索它只是将每一行读入变量“line”的行,然后你必须在该“line”中搜索你想要的文本。
size_t found=line.find("Package");
if (found!=std::string::npos) {
cout << line;
但这是一种处理XML的坏方法 - 没有什么能阻止XML编写器将标记分成多行。除非这是一次性的并且您创建文件,否则您应该使用通用XML解析器来读取文件并为您提供标记列表。
有许多非常容易使用的XML解析器,例如TinyXML
编辑(现在发布了不同的xml) - 这是使用正则表达式解析xml的问题,你不知道xml如何打破行。在编写自己的xml解析器之前,您可以继续添加越来越多的复杂层 - 只需使用What is the best open XML parser for C++?中的一个
答案 1 :(得分:4)
这不是解析XML文件的方式,但由于您不想使用解析器库,因此这段代码可能会让您入门。
文件: demo.xml
<? xml version="1.0" ?>
<fileStructure>
<Main_Package>
File_Navigate
</Main_Package>
<Dependency_Details>
<Dependency>
<Package>
xmlMetadata
</Package>
<Header>
xmlMetadata.h
</Header>
<Header_path>
C:\Dependency\xmlMetadata\xmlMetadata.h
</Header_path>
<Implementation>
xmlMetadata.cpp
</Implementation>
<Implementation_path>
C:\Dependency\xmlMetadata\xmlMetadata.cpp
</Implementation_path>
</Dependency>
<Dependency>
<Package>
xmlMetadata1
</Package>
<Header>
xmlMetadata1.h
</Header>
<Header_path>
C:\Dependency\xmlMetadata\xmlMetadata1.h
</Header_path>
<Implementation>
xmlMetadata1.cpp
</Implementation>
<Implementation_path>
C:\Dependency\xmlMetadata\xmlMetadata1.cpp
</Implementation_path>
</Dependency>
</Dependency_Details>
</fileStructure>
代码的基本思想是而你正在阅读文件的每个行,去掉开头的空白并存储 new -stripped-string 到 tmp ,然后尝试将其匹配到您要查找的其中一个标签。找到开始标记后,请继续打印以下行,直到找到 close-tag 。
文件: parse.cpp
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream in("demo.xml");
bool begin_tag = false;
while (getline(in,line))
{
std::string tmp; // strip whitespaces from the beginning
for (int i = 0; i < line.length(); i++)
{
if (line[i] == ' ' && tmp.size() == 0)
{
}
else
{
tmp += line[i];
}
}
//cout << "-->" << tmp << "<--" << endl;
if (tmp == "<Package>")
{
//cout << "Found <Package>" << endl;
begin_tag = true;
continue;
}
else if (tmp == "</Package>")
{
begin_tag = false;
//cout << "Found </Package>" << endl;
}
if (begin_tag)
{
cout << tmp << endl;
}
}
}
<强>输出:强>
xmlMetadata
xmlMetadata1
答案 2 :(得分:1)
文件上的单行标记很难描述为XML。无论如何,如果你真的想要解析一个XML文件,使用像RapidXML这样的解析器库可以更容易地实现这一点。 This page是一个很好的资源。
下面的代码是我尝试阅读以下XML(是的,XML文件必须有标题):
文件: demo.xml
<?xml version="1.0" encoding="utf-8"?>
<rootnode version="1.0" type="example">
<Package> xmlMetadata </Package>
</rootnode>
快速说明:rapidxml仅由标题组成。在我的系统上,我将库解压缩到/usr/include/rapidxml-1.13
,因此下面的代码可以编译为:
g++ read_tag.cpp -o read_tag -I/usr/include/rapidxml-1.13/
文件: read_tag.cpp
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <rapidxml.hpp>
using namespace std;
using namespace rapidxml;
int main()
{
string input_xml;
string line;
ifstream in("demo.xml");
// read file into input_xml
while(getline(in,line))
input_xml += line;
// make a safe-to-modify copy of input_xml
// (you should never modify the contents of an std::string directly)
vector<char> xml_copy(input_xml.begin(), input_xml.end());
xml_copy.push_back('\0');
// only use xml_copy from here on!
xml_document<> doc;
// we are choosing to parse the XML declaration
// parse_no_data_nodes prevents RapidXML from using the somewhat surprising
// behavior of having both values and data nodes, and having data nodes take
// precedence over values when printing
// >>> note that this will skip parsing of CDATA nodes <<<
doc.parse<parse_declaration_node | parse_no_data_nodes>(&xml_copy[0]);
// alternatively, use one of the two commented lines below to parse CDATA nodes,
// but please note the above caveat about surprising interactions between
// values and data nodes (also read http://www.ffuts.org/blog/a-rapidxml-gotcha/)
// if you use one of these two declarations try to use data nodes exclusively and
// avoid using value()
//doc.parse<parse_declaration_node>(&xml_copy[0]); // just get the XML declaration
//doc.parse<parse_full>(&xml_copy[0]); // parses everything (slowest)
// since we have parsed the XML declaration, it is the first node
// (otherwise the first node would be our root node)
string encoding = doc.first_node()->first_attribute("encoding")->value();
// encoding == "utf-8"
// we didn't keep track of our previous traversal, so let's start again
// we can match nodes by name, skipping the xml declaration entirely
xml_node<>* cur_node = doc.first_node("rootnode");
string rootnode_type = cur_node->first_attribute("type")->value();
// rootnode_type == "example"
// go straight to the first Package node
cur_node = cur_node->first_node("Package");
string content = cur_node->value(); // if the node doesn't exist, this line will crash
cout << content << endl;
}
<强>输出:强>
xmlMetadata