c++xmlxml-attributetinyxmltinyxml2

How to use Attribute as search keyword with TinyXML2(C++)


I'm trying use Attribute as keyword to find Element I want. it can work but only when it is first element.

bool readXML(){
string gateWay_str="",user_Input="";
XMLDocument XML_file;
XML_file.LoadFile("exception_ip.xml");                      //XML file Name
XMLHandle docHandle( &XML_file );                           //XMLHandle
XMLNode* node_ctrl;                                         //Node pointer
XMLElement* gateWay_Ele = docHandle.FirstChildElement("exception_ip").FirstChildElement("ip").ToElement();  //Get Node by XMLHandle and turn to Element 
cout<<"Test ip3=";                                          //show to user 
cin>>user_Input;                                            //user input

if(gateWay_Ele){                                            //is gateWay_Ele null?
    gateWay_str=gateWay_Ele->Name();                        //get Element name and show
    cout<< "Got gateWay_Ele = "<<gateWay_str<<endl;
}
if(gateWay_Ele ->Attribute("ip3",(user_Input.c_str()))){    //find Attribute where ip3 = "user input"
        node_ctrl=gateWay_Ele->FirstChild();                //make node_ctrl point FirstChild
        if(node_ctrl==nullptr){                             //is nullptr?
            cout<<"node_ctrl = nullptr";
            return false;
        }
        else{                                               
            gateWay_Ele=node_ctrl->ToElement();             //turn node_ctel to Element
            gateWay_str = gateWay_Ele->GetText();           //get Text
            cout<<"GateWay = "<<gateWay_str<<endl;          //show
            return true;                                    //return true
        }
    }
return false;

}

and my XML is

<?xml version="1.0" ?> 
<exception_ip>  
	<ip ip3="23">	
      <gateway>123.123.23.1</gateway>
      <dnsp>dnsp23</dnsp>
      <dnss>dnss23</dnss>
	</ip>
	<ip ip3="24">	
      <gateway>123.123.24.1</gateway>
      <dnsp>dnsp24</dnsp>
      <dnss>dnss24</dnss>
	</ip>
</exception_ip>

It work only when input is 23

and I had tried use NextSiblingElement("ip") to make point keep going to next sibling element. but it just infinite loop

do{
if(gateWay_Ele ->Attribute("ip3",(user_Input.c_str()))){    //find Attribute where ip3 = "user input"
        node_ctrl=gateWay_Ele->FirstChild();                //make node_ctrl point FirstChild
        if(node_ctrl==nullptr){                             //is nullptr?
            cout<<"node_ctrl = nullptr";
            return false;
        }
        else{                                               
            gateWay_Ele=node_ctrl->ToElement();             //turn node_ctel to Element
            gateWay_str = gateWay_Ele->GetText();           //get Text
            cout<<"GateWay = "<<gateWay_str<<endl;          //show
            return true;                                    //return true
        }
    }
else{
    gateWay_Ele->NextSiblingElement("ip");
}
}while(true);

Thanks !


Solution

  • You need to iterate over all "ip" elements, testing the "ip3" attribute until you find the one you want. But here's an easy way to do it using my tinyxml2 extension :

    #include <string>
    #include <iostream>
    #include <conio.h>  // for _getch()
    // include the header for tinyxml2ex which includes tinyxml2, remember to put them on your include path
    #include "tixml2ex.h"
    
    using namespace std;
    
    int main()
    {
        // put the XML into a string for simplicity
        string testXml{ R"-(
    <?xml version="1.0" ?>
    <exception_ip>
        <ip ip3="23">
            <gateway>123.123.23.1</gateway>
            <dnsp>dnsp23</dnsp>
            <dnss>dnss23</dnss>
        </ip>
        <ip ip3="24">
            <gateway>123.123.24.1</gateway>
            <dnsp>dnsp24</dnsp>
            <dnss>dnss24</dnss>
        </ip>
    </exception_ip>
    )-"s };
    
        auto doc = tinyxml2::load_document (testXml);
        // find the required element by XPath and list its member elements
        if (auto ip = find_element (*doc, "/exception_ip/ip[@ip3='24']"s))
        {
            for (auto e : ip)
                cout << e->Name() << " " << text (e) << endl;
        }
        else
            cout << "could not find ip element" << endl;
    
       return 0;
    }