繁体   English   中英

使用C ++从xml文件中读取一行

[英]Read a line from xml file using C++

我的XML文件有:

<Package> xmlMetadata </ Package>

我正在此文件中搜索标签,并且必须在控制台上打印此标签的开始和结束标签之间的文本。 即在这种情况下,我希望在控制台上打印xmlMetadata。 同样,它应该在文件中更进一步,如果它遇到同一文件中的另一个<Package>标记,则再次打印。

这是我的代码,但它是打印整个文件的内容:

{
    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 >

Getline不会搜索它只是将每一行读入变量“line”的行,然后你必须在该“行”中搜索你想要的文本。

   size_t found=line.find("Package");
   if (found!=std::string::npos) {
       cout << line;

但这是一种处理XML的坏方法 - 没有什么能阻止XML编写器将标记分成多行。 除非这是一次性的并且您创建文件,否则您应该使用通用XML解析器来读取文件并为您提供标记列表。

有许多非常容易使用的XML解析器,例如TinyXML

编辑(现在发布了不同的xml) - 这是使用正则表达式解析xml的问题,你不知道xml如何打破行。 在编写自己的xml解析器之前,您可以继续添加越来越多的复杂层 - 只需使用什么是C ++的最佳开放XML解析器?

这不是解析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>

代码的基本思想是读取文件的每一行时去除开头的空白区域并将新的条带化字符串存储到tmp中 ,然后尝试将其与其中一个标记相匹配寻找。 找到begin-tag后 ,继续打印以下行,直到找到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

文件上的单行标记很难描述为XML。 无论如何,如果你真的想要解析一个XML文件,使用像RapidXML这样的解析器库可以更容易地实现这一点 此页面是一个很好的资源。

下面的代码是我尝试阅读以下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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM