C ++如何使用boost XML解析器,并存储在地图读取XML [英] c++ How to read XML using boost xml parser and store in map

查看:197
本文介绍了C ++如何使用boost XML解析器,并存储在地图读取XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为一个例子,我使用这里列出的XML文件:

  https://msdn.microsoft.com/en-us/library/ms256129(V = vs.110)的.aspx

XML文件:

 <?XML版本=1.0&GT?;
< purchaseOrder中的xmlns =htt​​p://tempuri.org/po.xsdorderDate存储=1999-10-20>
    < SHIPTO国家=US>
        <名称>爱丽丝·史密斯< /名称>
        <街道> 123枫树街< /街道>
        <城市>米尔谷< /城市>
        <州及GT; CA< /州>
        <邮编及GT; 90952< /拉链>
    < / SHIPTO>
    <帐单寄给国家=US>
        <名称>罗伯特·史密斯< /名称>
        <街→8橡树大道< /街道>
        <城市>旧城区和LT; /城市>
        <州及GT; PA< /州>
        <邮编及GT; 95819< /拉链>
    < /帐单寄给>
    <注释和GT,快点,我的草坪是怎么回事野生<!/评论>
    <项目>
        <项目partNum =872-AA>
            <&PRODUCTNAME GT;&割草机LT; /产品名称>
            <数量> 1 LT; /数量>
            <价格>
                < USPrice> 148.95< / USPrice>
                < UKPrice> 150.02< / UKPrice>
            < /价格>
            <注释和GT;确认这是电力和LT; /评论>
        < /项目>
        <项目partNum =926-AA>
            <&PRODUCTNAME GT;婴儿监视器< /产品名称>
            <数量> 1 LT; /数量>
            <价格>
                < USPrice>及39.95 LT; / USPrice>
                < UKPrice>及37.67 LT; / UKPrice>
            < /价格>
            < USPrice>及39.98 LT; / USPrice>
            <&SHIPDATE GT; 1999年5月21日< / SHIPDATE>
        < /项目>
    < /项目>
< / purchaseOrder的>

目前我使用下面的code,但使用我能够只读一个是purchaseOrder.shipTo国家只有子节点。如何读取到标签USPrice?确实提升XML解析器支持4级标记值分析?

 常量标准::字符串XML_PATH1 =./test1.xml;
#定义ROOTTAGpurchaseOrder的
    提高:: property_tree :: ptree中PT;
    提高:: property_tree :: read_xml(XML_PATH1,PT);
    BOOST_FOREACH(升压:: property_tree :: ptree中:: VALUE_TYPE&安培; V,pt.get_child(ROOTTAG)){
        xmlmap [v.first.data()] = v.second.data();
    }

我要读取和存储在如下 xmlmap<字符串,字符串方式>

 地图键= items.item partNum.USPrice
图值= 39.98(后转换为字符串)

更新:

我试过以下,但它给我的编译误差

 错误:提振:: property_tree :: ptree中没有名为'第二'成员
                         提高:: property_tree :: ptree中LT = subtree.second;

code:

 常量标准::字符串XML_PATH1 =./test1.xml;
#定义ROOTTAGpurchaseOrder的
提高:: property_tree :: ptree中PT1;
提高:: property_tree :: read_xml(XML_PATH1,PT1);
BOOST_FOREACH(升压:: property_tree :: ptree中:: VALUE_TYPE&放大器;节点,pt1.get_child(ROOTTAG))
{
    标准::字符串标记名= node.first;
    标记名+ =。
    提高:: property_tree :: ptree中子树= node.second;
    BOOST_FOREACH(升压:: property_tree :: ptree中:: VALUE_TYPE&安培; V,subtree.get_child(node.first.data()))
    {
        提高:: property_tree :: ptree中LT = subtree.second;
        标记名+ = v.first.data();
        标记名+ =。
        BOOST_FOREACH(升压:: property_tree :: ptree中:: VALUE_TYPE&放大器; VT,lt.get_child(v.first.data()))
            {
                标准::字符串名称1 = vt.first.data();
                标记名+ = NAME1;
                如果(名称1 =!< xmlattr>){
                    标准::字符串tagvalue = lt.get<标准::字符串>(名称1);
                    标记名+ = NAME1;
                    xmlmap [标签名称] = tagvalue;
                    }
             }
      }
}


解决方案

这似乎是一个真没用的事。

一个属性树是/已经/那结构图:

 汽车PO = pt.get_child(purchaseOrder的);
性病::法院LT&;< items.item.Price.USPrice:'<< po.get(items.item.Price.USPrice,)下;&下; '\\ n;

如果你想要的XPath,使用XPath能够XML库(什么XML解析器,我应该用C ++使用?)。

如果你想更轻松地访问,写一些翻译或访问功能。但是,不管你做什么,你可能做的希望通过结构的信息了,因为你的问题类型的说明。

下面是我觉得有用的东西示例:

<大骨节病> 住在Coliru

 的#include&LT;升压/ property_tree / xml_parser.hpp&GT;
#包括LT&;升压/多precision / cpp_dec_float.hpp&GT;
#包括LT&;&iostream的GT;
#包括LT&;地图和GT;使用十进制=的boost ::多precision :: cpp_dec_float_50;
使用树=的boost :: property_tree :: ptree中;命名空间的BackOffice {
    结构purchaseOrder的{
        结构的地址{
            标准::字符串的国家,名称,街道,城市,州,邮编;
        } SHIPTO,收单方;        标准::字符串评论;        结构件{
            标准::字符串partNum,产品名称,评论;
            为size_t数量;            结构价格{
                十进制USPrice,UKPrice;
            } 价钱;
        };        的std ::矢量&lt;&项目GT;项目;
    };    无效read_tree(树常量和放大器;树,purchaseOrder的::地址和放大器;成);
    无效read_tree(树常量和放大器;树,purchaseOrder的::项目::价格和放大器;成);
    无效read_tree(树常量和放大器;树,purchaseOrder的::项目&安培;成);
    无效read_tree(树常量和放大器;树,purchaseOrder的&安培;成);    模板&LT; typename的T,typename的间接&GT;
    无效read_tree(间接常量和放大器; maybeTree,T&安培;成,decltype(安培; * maybeTree)= nullptr){
        如果(maybeTree)read_tree(* maybeTree,成);其他进入= {};
    }    模板&LT; typename的T,typename的间接&GT;
    无效read_tree(间接常量和放大器; maybeTree,性病::串子,T&安培;成,decltype(安培; * maybeTree)= nullptr){
        如果(maybeTree)read_tree(* maybeTree,子,成);其他进入= {};
    }
    模板&LT; typename的T&GT;
    无效read_tree(树常量和放大器;树的std ::串子,性病::矢量&lt; T&GT;&安培;进入){
        为(自动&安培;儿童:树){
            如果(child.first ==子){
                into.emplace_back();
                read_tree(child.second,into.back());
            }
        }
    }    无效read_tree(树常量和放大器;树,purchaseOrder的::地址和放大器;进入){
        into.country = tree.get(&所述; xmlattr&GT; .country,(未知);
        into.name = tree.get(名,(未知);
        into.street = tree.get(街道,(未知);
        into.city = tree.get(城市,(未知);
        into.state = tree.get(国家,(未知);
        into.zip = tree.get(ZIP,(未知);
    }    无效read_tree(树常量和放大器;树,purchaseOrder的::项目::价格和放大器;进入){
        into.UKPrice = tree.get(UKPrice,小数{});
        into.USPrice = tree.get(USPrice,小数{});
    }    无效read_tree(树常量和放大器;树,purchaseOrder的::项目&安培;进入){
        into.partNum = tree.get(&所述; xmlattr&GT; .partNum,(未知);
        into.productName = tree.get(产品名称,(未知);
        into.comment = tree.get(评论,);
        read_tree(tree.get_child_optional(价格),into.price);
    }    无效read_tree(树常量和放大器;树,purchaseOrder的&安培;进入){
        read_tree(tree.get_child_optional(SHIPTO),into.shipTo);
        read_tree(tree.get_child_optional(收单方),into.billTo);
        read_tree(tree.get_child_optional(项目),项,into.items);
        into.comment = tree.get(评论,);
    }}诠释主(){
    树PT;
    read_xml(input.txt的PT);    //自动PO = pt.get_child(purchaseOrder的);
    //性病::法院LT&;&LT; items.item.Price.USPrice:'&LT;&LT; po.get(items.item.Price.USPrice,)下;&下; '\\ n;    ::的BackOffice婆purchaseOrder的;
    read_tree(pt.get_child(purchaseOrder中),PO);
}

As an example I am using the XML file listed here:

https://msdn.microsoft.com/en-us/library/ms256129(v=vs.110).aspx

The XML File:

<?xml version="1.0"?>
<purchaseOrder xmlns="http://tempuri.org/po.xsd" orderDate="1999-10-20">
    <shipTo country="US">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <city>Mill Valley</city>
        <state>CA</state>
        <zip>90952</zip>
    </shipTo>
    <billTo country="US">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <city>Old Town</city>
        <state>PA</state>
        <zip>95819</zip>
    </billTo>
    <comment>Hurry, my lawn is going wild!</comment>
    <items>
        <item partNum="872-AA">
            <productName>Lawnmower</productName>
            <quantity>1</quantity>
            <Price>
                <USPrice>148.95</USPrice>
                <UKPrice>150.02</UKPrice>
            </Price>
            <comment>Confirm this is electric</comment>
        </item>
        <item partNum="926-AA">
            <productName>Baby Monitor</productName>
            <quantity>1</quantity>
            <Price>
                <USPrice>39.95</USPrice>
                <UKPrice>37.67</UKPrice>
            </Price>
            <USPrice>39.98</USPrice>
            <shipDate>1999-05-21</shipDate>
        </item>
    </items>
</purchaseOrder>

Currently I am using the following code but using that I am able to read only one child node that is purchaseOrder.shipTo country only. how to read till tag USPrice? Does boost xml parser support 4 level tag value parsing?

const std::string XML_PATH1 = "./test1.xml";
#define ROOTTAG  "purchaseOrder"
    boost::property_tree::ptree pt;
    boost::property_tree::read_xml( XML_PATH1, pt);
    BOOST_FOREACH(boost::property_tree::ptree::value_type & v, pt.get_child(ROOTTAG)){
        xmlmap[v.first.data()] = v.second.data();
    }

I want to read and store as follows in the xmlmap <string, string>.

map key = items.item partNum.USPrice
map value = 39.98 (post converting to string)

Update:

I tried the following but it is giving me compilation error as

error: ‘boost::property_tree::ptree’ has no member named ‘second’
                         boost::property_tree::ptree lt = subtree.second;

Code:

const std::string XML_PATH1 = "./test1.xml";
#define ROOTTAG  "purchaseOrder"
boost::property_tree::ptree pt1;
boost::property_tree::read_xml( XML_PATH1, pt1);
BOOST_FOREACH(boost::property_tree::ptree::value_type & node, pt1.get_child(ROOTTAG))
{
    std::string tagname = node.first;
    tagname += ".";
    boost::property_tree::ptree subtree = node.second;
    BOOST_FOREACH( boost::property_tree::ptree::value_type & v, subtree.get_child(node.first.data()))
    {
        boost::property_tree::ptree lt = subtree.second;
        tagname += v.first.data();
        tagname += ".";
        BOOST_FOREACH( boost::property_tree::ptree::value_type & vt, lt.get_child(v.first.data()))
            {
                std::string name1 = vt.first.data();
                tagname += name1;
                if(name1 != "<xmlattr>") {
                    std::string tagvalue = lt.get<std::string>(name1);
                    tagname += name1;
                    xmlmap[tagname] = tagvalue;
                    }
             }
      }
}

解决方案

It seems like a really useless thing to do.

A property tree is /already/ that "structured map":

auto po = pt.get_child("purchaseOrder");
std::cout << "items.item.Price.USPrice: '" << po.get("items.item.Price.USPrice", "") << "'\n";

If you want XPath, use an XPath capable XML library (What XML parser should I use in C++?).

If you want easier access, write some translators or access functions. But whatever you do, you probably do not wish to through the structural information away, as your question kind of suggests.

Here's a sample of something I'd find useful:

Live On Coliru

#include <boost/property_tree/xml_parser.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
#include <map>

using Decimal = boost::multiprecision::cpp_dec_float_50;
using Tree    = boost::property_tree::ptree;

namespace BackOffice {
    struct purchaseOrder {
        struct address {
            std::string country, name, street, city, state, zip;
        } shipTo, billTo;

        std::string comment;

        struct item {
            std::string partNum, productName, comment;
            size_t quantity;

            struct Price { 
                Decimal USPrice, UKPrice;
            } price;
        };

        std::vector<item> items;
    };

    void read_tree(Tree const& tree, purchaseOrder::address& into);
    void read_tree(Tree const& tree, purchaseOrder::item::Price& into);
    void read_tree(Tree const& tree, purchaseOrder::item& into);
    void read_tree(Tree const& tree, purchaseOrder& into);

    template <typename T, typename Indirect>
    void read_tree(Indirect const& maybeTree, T& into, decltype(&*maybeTree) = nullptr) {
        if (maybeTree) read_tree(*maybeTree, into); else into = {};
    }

    template <typename T, typename Indirect>
    void read_tree(Indirect const& maybeTree, std::string sub, T& into, decltype(&*maybeTree) = nullptr) {
        if (maybeTree) read_tree(*maybeTree, sub, into); else into = {};
    }


    template <typename T>
    void read_tree(Tree const& tree, std::string sub, std::vector<T>& into) {
        for (auto& child : tree) {
            if (child.first == sub) {
                into.emplace_back();
                read_tree(child.second, into.back());
            }
        }
    }

    void read_tree(Tree const& tree, purchaseOrder::address& into) {
        into.country = tree.get("<xmlattr>.country", "(unknown");
        into.name    = tree.get("name",              "(unknown");
        into.street  = tree.get("street",            "(unknown");
        into.city    = tree.get("city",              "(unknown");
        into.state   = tree.get("state",             "(unknown");
        into.zip     = tree.get("zip",               "(unknown");
    }

    void read_tree(Tree const& tree, purchaseOrder::item::Price& into) {
        into.UKPrice = tree.get("UKPrice", Decimal{});
        into.USPrice = tree.get("USPrice", Decimal{});
    }

    void read_tree(Tree const& tree, purchaseOrder::item& into) {
        into.partNum     = tree.get("<xmlattr>.partNum", "(unknown");
        into.productName = tree.get("productName",       "(unknown");
        into.comment     = tree.get("comment",           "");
        read_tree(tree.get_child_optional("Price"), into.price);
    }

    void read_tree(Tree const& tree, purchaseOrder& into) {
        read_tree(tree.get_child_optional("shipTo"), into.shipTo);
        read_tree(tree.get_child_optional("billTo"), into.billTo);
        read_tree(tree.get_child_optional("items"), "item", into.items);
        into.comment = tree.get("comment", "");
    }

}

int main() {
    Tree pt;
    read_xml( "input.txt", pt);

    //auto po = pt.get_child("purchaseOrder");
    //std::cout << "items.item.Price.USPrice: '" << po.get("items.item.Price.USPrice", "") << "'\n";

    BackOffice::purchaseOrder po;
    read_tree(pt.get_child("purchaseOrder"), po);
}

这篇关于C ++如何使用boost XML解析器,并存储在地图读取XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆