BOOST XML解析

BOOST XML解析相同Tag子节点

主要用到了BOOST_FOREACH宏,对ptree进行遍历:

int SecSrcmConf::readFromXML() {
    ifstream file;
    file.open(m_confFilePath.c_str(), ios::in);
    if (!file.is_open()) {
        cerr << "File " << m_confFilePath << " open failed" << endl;
        return -1;
    }
    file.close();
    ptree pt;
    read_xml(m_confFilePath, pt, xml_parser::trim_whitespace);
    parseSystemInfoFromXML(pt.get_child("SRCM.System"));
    parseMMIInfoFromXML(pt.get_child("SRCM.MMI"));
    BOOST_FOREACH (ptree::value_type &v, pt.get_child("SRCM")) {
        string tmp;
        if (v.first == "Substation") {
            SrcmSubConf subConf;
            subConf.m_subName = v.second.get<string>("Name");
            tmp = v.second.get<string>("Protocol");
            if (tmp.length()) {
                if (tmp == "ext104" || tmp == "EXT104") {
                    subConf.m_protocolType = PROTOCOL_EXT104;
                } else if (tmp == "iec61850" || tmp == "IEC61850") {
                    subConf.m_protocolType = PROTOCOL_IEC61850;
                } else {
                    subConf.m_protocolType = PROTOCOL_NULL;
                }
            }
            tmp = v.second.get<string>("Compress");
            if (tmp.length()) {
                if (tmp == "ZIP" || tmp == "zip") {
                    subConf.m_compressType = COMPRESS_ZIP;
                } else if (tmp == "GZIP" || tmp == "gzip" ||
                    tmp == "GZ" || tmp == "gz") {
                    subConf.m_compressType = COMPRESS_GZIP;
                } else {
                    subConf.m_compressType = COMPRESS_NULL;
                }
            }
            subConf.m_cimLastUpdate = str2time(
                v.second.get<string>("DeviceCIMFile.LastUpdateTime"));
            subConf.m_cimLastImport = str2time(
                v.second.get<string>("DeviceCIMFile.LastImportTime"));
            subConf.m_svgLastUpdate = str2time(
                v.second.get<string>("DeviceSVGFile.LastUpdateTime"));
            subConf.m_svgLastImport = str2time(
                v.second.get<string>("DeviceSVGFile.LastImportTime"));
            subConf.m_mapLastUpdate = str2time(
                v.second.get<string>("DeviceMAPFile.LastUpdateTime"));
            subConf.m_mapLastImport = str2time(
                v.second.get<string>("DeviceMAPFile.LastImportTime"));
            m_subConfMap.insert(pair<string, SrcmSubConf>(subConf.m_subName, subConf));
        }
    }
    return 0;
}


BOOST XML解析中文问题

ptree解析主要的xml文件的格式是utf-8格式的,如果xml文件中含有unicode如中文字符,解析出来就是乱码。解析unicode要用wptree,该类的接口均支持宽字符并且接口和ptree保持一致。要支持中文解析仅仅wptree还不够,还需要一个unicode转换器的帮助,该转换器可以实现宽字符和窄字符的转换,宽窄的互相转换函数有很多实现,不过c++11中有更简单统一的方式实现宽窄字符的转换。

c++11中宽窄字符的转换:

std::wstring_convert<std::codecvt<wchar_t,char,std::mbstate_t>> conv

(newstd::codecvt<wchar_t,char,std::mbstate_t>("CHS"));
//宽字符转为窄字符
string str = conv.to_bytes(L"你好");
//窄字符转为宽字符
string wstr = conv.from_bytes(str);

boost.property_tree在解析含中文的xml文件时,需要先将该文件转换一下。boost解决方法:

#include "boost/program_options/detail/utf8_codecvt_facet.hpp"
void ParseChn()
{
    std::wifstream f(fileName);
    std::locale utf8Locale(std::locale(), new boost::program_options::detail::utf8_codecvt_facet());
    f.imbue(utf8Locale); //先转换一下

    //用wptree去解析
    property_tree::wptree ptree;
    property_tree::read_xml(f, ptree);    
}

这种方法有个缺点就是要引入boost的libboost_program_options库,该库有二十多M,仅仅是为了解决一个中文问题,却要搞得这么麻烦,有点得不偿失。好在c++11提供更简单的方式,用c++11可以这样:

void Init(const wstring& fileName, wptree& ptree)
    {
        std::wifstream f(fileName);
        std::locale utf8Locale(std::locale(), new std::codecvt_utf8<wchar_t>);
        f.imbue(utf8Locale); //先转换一下

        //用wptree去解析
        property_tree::read_xml(f, ptree);
    }

用c++11就不需要再引入boost的libboost_program_options库了,很简单。另外一种方法就是,仍然用ptree和string,只是在取出string字符串后,做一个转换为unicode的转换,就能得到中文字符串了。例如:

auto child = item.second.get_child("Scenes.Scene");
auto oname = child.get_optional<string>("<xmlattr>.Name");

//oname内部存了一个unicode字符串,需要将其转换为宽字符串得到中文
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring wide = converter.from_bytes(*oname);

//宽字符串转为窄字符串
//std::string narrow = converter.to_bytes(L"foo");

BOOST 写入XML文件格式问题

主要使用到了boost::property_tree::xml_writer_settings。如果编译器用到了C++11,用下面的写法表示缩进两个空格:

boost::property_tree::xml_writer_settings<char> settings(' ',2);
boost::property_tree::write_xml(filename, pt,std::local(),settings);
如果没有C++11特性,那么使用xml_writer_make_settings方法:

boost::property_tree::xml_writer_settings<string> settings =
    bp::xml_writer_make_settings<string>(' ', 2);
boost::property_tree::write_xml(xml_path, root, locale(), settings);






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要修改一个 XML 文件中的某一项,可以使用 Boost XML 库提供的 API 来实现: 1. 首先,需要读取 XML 文件,并将其解析为 XML 对象,可以使用 `boost::property_tree::xml_parser::read_xml` 函数来实现。 ```c++ boost::property_tree::ptree pt; boost::property_tree::xml_parser::read_xml("example.xml", pt); ``` 2. 然后,需要找到需要修改的 XML 节点,可以使用 `boost::property_tree::ptree::get_child` 函数获取指定节点的子节点。 ```c++ boost::property_tree::ptree& node = pt.get_child("root.node_to_modify"); ``` 3. 接下来,可以通过修改节点的值来对其进行修改。 ```c++ node.put_value("new_value"); ``` 4. 最后,需要将修改后的 XML 对象重新写入文件,可以使用 `boost::property_tree::xml_parser::write_xml` 函数来实现。 ```c++ boost::property_tree::xml_parser::write_xml("example.xml", pt); ``` 完整的代码如下: ```c++ #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <iostream> int main() { boost::property_tree::ptree pt; boost::property_tree::xml_parser::read_xml("example.xml", pt); boost::property_tree::ptree& node = pt.get_child("root.node_to_modify"); node.put_value("new_value"); boost::property_tree::xml_parser::write_xml("example.xml", pt); return 0; } ``` 注意,以上代码只是修改了内存中的 XML 对象,并没有直接修改文件。如果需要直接修改文件,可以在写入文件之前先将原文件备份,然后再写入修改后的 XML 对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值