Proper way to parse XML using pugixml

自闭症网瘾萝莉.ら 提交于 2021-02-19 05:35:08

问题


I have an XML file that I need to parse and I'm struggling with using PugiXML to parse out all elements and attributes.

I have the following XML file:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <PanelList DefaultTheme="konami" >
            <Panel xpos="0" ypos="0" width="800" height="600" imagepath="./%THEME%/background_uga_large.png" name="AttractMode0" >
                <GameViewport xpos="0" ypos="0" width="630" height="526" name="gameviewport"/>
                <ValueLabel xpos="120" ypos="550" width="448" height="30" fontsize="18" color="white" text="Please, insert your card" name="StatusAttract" errorimagepath="./%THEME%/panel_top_error.png" pageattpendingpath="./%THEME%/panel_top_att.png" drinkpendingpath="./%THEME%/panel_top_drink.png" onclick="ShowPanel(special_panel999)" />
                <StreamingImage xpos="637" ypos="3" width="160" height="120" volume="0" text="udp:@:9001" name="attract1" />
                <Image xpos="637" ypos="130" width="160" height="390" imagepath="http://n2web/images/attract-uga.gif" />
                <FunctionButton xpos="6" ypos="534" width="68" height="60" imagepath="./%THEME%/button_shrink.png" clickimagepath="./%THEME%/button_shrink_down.png" name="window" onclick="ShowPanel(AttractModeSmall)"/>
                <FunctionButton xpos="650" ypos="534" width="68" height="60" imagepath="./%THEME%/button_attendantstart_up.png" clickimagepath="./%THEME%/button_attendantstart_down.png" name="pageattstart" onclick="PageAttendantRequest" enable="MW_ONLINE == TRUE"/>
                <FunctionButton xpos="725" ypos="534" width="68" height="60" imagepath="./%THEME%/button_drinkstart_up.png" clickimagepath="./%THEME%/button_drinkstart_down.png" name="drinkstart" onclick="DrinkRequest" enable="MW_ONLINE == TRUE"/>
            </Panel>

            <Panel xpos="0" ypos="0" width="800" height="600" imagepath="./%THEME%/background_uga_large.png" name="AttractMode1" >
                <GameViewport xpos="0" ypos="0" width="630" height="526" name="gameviewport"/>
                <ValueLabel xpos="120" ypos="550" width="448" height="30" fontsize="18" color="white" text="Please, insert your card" name="StatusAttract" errorimagepath="./%THEME%/panel_top_error.png" pageattpendingpath="./%THEME%/panel_top_att.png" drinkpendingpath="./%THEME%/panel_top_drink.png" onclick="ShowPanel(special_panel999)" />
                <StreamingImage xpos="637" ypos="3" width="160" height="120" volume="0" text="udp:@:9001" name="attract1" />
                <Image xpos="637" ypos="130" width="160" height="390" imagepath="http://n2web/images/attract-uga.gif" />
                <FunctionButton xpos="6" ypos="534" width="68" height="60" imagepath="./%THEME%/button_shrink.png" clickimagepath="./%THEME%/button_shrink_down.png" name="window" onclick="ShowPanel(AttractModeSmall)"/>
                <FunctionButton xpos="650" ypos="534" width="68" height="60" imagepath="./%THEME%/button_attendantstart_up.png" clickimagepath="./%THEME%/button_attendantstart_down.png" name="pageattstart" onclick="PageAttendantRequest" enable="MW_ONLINE == TRUE"/>
                <FunctionButton xpos="725" ypos="534" width="68" height="60" imagepath="./%THEME%/button_drinkstart_up.png" clickimagepath="./%THEME%/button_drinkstart_down.png" name="drinkstart" onclick="DrinkRequest" enable="MW_ONLINE == TRUE"/>
            </Panel>    
</PanelList>

With the following code I can get the attributes of each of the two "Panel" objects.

#include "pugixml.hpp"
#include <iostream>

int main()
{
    pugi::xml_document doc;
    if (!doc.load_file("allpanels.xml")) return -1;


    pugi::xml_node panels = doc.child("PanelList");

    std::cout << panels.name() << std::endl;

    for (pugi::xml_node panel = panels.first_child(); panel; panel = panel.next_sibling())
    {
        std::cout << panel.name() << std::endl;

        for (pugi::xml_attribute attr = panel.first_attribute(); attr; attr = attr.next_attribute())
        {
            std::cout << " " << attr.name() << "=" << attr.value() << std::endl;
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

The output is as follows:

jrnVM gtkSign $ ./gtkSign 
PanelList
Panel
 xpos=0
 ypos=0
 width=800
 height=600
 imagepath=./%THEME%/background_uga_large.png
 name=AttractMode0

Panel
 xpos=0
 ypos=0
 width=800
 height=600
 imagepath=./%THEME%/background_uga_large.png
 name=AttractMode1

I can see that I'm getting the attributes for each of the two "Panel" objects, but not the elements for each. Each "Panel" object in the file will have different elements so I can't traverse the tree looking for particular elements or attributes.

The question is: How do I modify the code so that I can iterate though all of the "Panel" objects and get all of the information for each one?

Any help would be greatly appreciated.

EDIT:

With the help of "john" I was able to come up with this solution. Thanks John.

#include "pugixml.hpp"
#include <iostream>
#include <sstream>

int main()
{
    pugi::xml_document doc;
    std::string namePanel;

    if (!doc.load_file("allpanels.xml")) return -1;


    pugi::xml_node panels = doc.child("PanelList");

    std::cout << panels.name() << std::endl;

    for (pugi::xml_node panel = panels.first_child(); panel; panel = panel.next_sibling())
    {
        //We found a "Panel" -- print it's attributes
        for (pugi::xml_attribute attr = panel.first_attribute(); attr; attr = attr.next_attribute())
        {
            std::cout << " " << attr.name() << "=" << attr.value() << std::endl;

            std::string attrName = attr.name();
            if( !attrName.compare("name") )
            {
                namePanel = attr.value();
            }
        }
        std::cout << std::endl;

        std::cout << "Panel: "  << namePanel << std::endl;
        //Now print all elements and attributes of current "Panel"
        for (pugi::xml_node child = panel.first_child(); child; child = child.next_sibling())
        {
            std::cout << child.name() << std::endl;     // get element name
            // iterate through all attributes
            for (pugi::xml_attribute attr = child.first_attribute(); attr; attr = attr.next_attribute())
            {
                std::cout << " " << attr.name() << "=" << attr.value() << std::endl;
            }
            std::cout << std::endl;
        }
    }
    std::cout << std::endl;
}

EDIT: The above works, but I can't help but think there is a better way that involves a single loop.

来源:https://stackoverflow.com/questions/16155888/proper-way-to-parse-xml-using-pugixml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!