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.