使用pugixml解析XML的正确方法

时间:2013-04-22 20:13:25

标签: c++ xml xml-parsing pugixml

我有一个需要解析的XML文件,我正在努力使用PugiXML来解析所有元素和属性。

我有以下XML文件:

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

使用以下代码,我可以获得两个“Panel”对象中每个对象的属性。

#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;
}

输出如下:

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

我可以看到我正在获取两个“Panel”对象中每个对象的属性,但不是每个对象的元素。文件中的每个“Panel”对象都有不同的元素,因此我无法遍历树中查找特定元素或属性。

问题是:如何修改代码,以便我可以遍历所有“Panel”对象并获取每个对象的所有信息?

非常感谢任何帮助。

修改

在“约翰”的帮助下,我能够提出这个解决方案。谢谢约翰。

#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;
}

编辑:上述工作正常,但我不禁想到有更好的方法涉及单个循环。

0 个答案:

没有答案