Search code examples
cstringparsingxml-rpc

XMLRPC C Library. Parse an array with variable number of structures


I have an XML as below. It is array of structures. Structure inside an array have fixed number of elements, but array may have one or more sructures and beforehand we can't know how many. The documentation describes parsing of fixed amount of XML elements. How should I use xmlrpc_parse_value() function from xmlrpc library to parse such XML:

<methodResponse>
   <params>
      <param>
         <value>
            <array>
               <data>
                  <value>
                     <struct>
                        <member>
                           <name>description</name>
                           <value>
                              <string>pid 32569, uptime 0:00:23</string>
                           </value>
                        </member>
                        <member>
                           <name>pid</name>
                           <value>
                              <int>32569</int>
                           </value>
                        </member>
                        <member>
                           <name>stderr_logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.err.log</string>
                           </value>
                        </member>
                        <member>
                           <name>stop</name>
                           <value>
                              <int>1519310402</int>
                           </value>
                        </member>
                        <member>
                           <name>logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.out.log</string>
                           </value>
                        </member>
                        <member>
                           <name>exitstatus</name>
                           <value>
                              <int>0</int>
                           </value>
                        </member>
                        <member>
                           <name>spawnerr</name>
                           <value>
                              <string />
                           </value>
                        </member>
                        <member>
                           <name>now</name>
                           <value>
                              <int>1519310425</int>
                           </value>
                        </member>
                        <member>
                           <name>group</name>
                           <value>
                              <string>lp-se</string>
                           </value>
                        </member>
                        <member>
                           <name>name</name>
                           <value>
                              <string>lp-se_0</string>
                           </value>
                        </member>
                        <member>
                           <name>statename</name>
                           <value>
                              <string>RUNNING</string>
                           </value>
                        </member>
                        <member>
                           <name>start</name>
                           <value>
                              <int>1519310402</int>
                           </value>
                        </member>
                        <member>
                           <name>state</name>
                           <value>
                              <int>20</int>
                           </value>
                        </member>
                        <member>
                           <name>stdout_logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.out.log</string>
                           </value>
                        </member>
                     </struct>
                  </value>
                  <value>
                     <struct>
                        <member>
                           <name>description</name>
                           <value>
                              <string>pid 31107, uptime 0:02:21</string>
                           </value>
                        </member>
                        <member>
                           <name>pid</name>
                           <value>
                              <int>31107</int>
                           </value>
                        </member>
                        <member>
                           <name>stderr_logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.err.log</string>
                           </value>
                        </member>
                        <member>
                           <name>stop</name>
                           <value>
                              <int>1519310284</int>
                           </value>
                        </member>
                        <member>
                           <name>logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.out.log</string>
                           </value>
                        </member>
                        <member>
                           <name>exitstatus</name>
                           <value>
                              <int>0</int>
                           </value>
                        </member>
                        <member>
                           <name>spawnerr</name>
                           <value>
                              <string />
                           </value>
                        </member>
                        <member>
                           <name>now</name>
                           <value>
                              <int>1519310425</int>
                           </value>
                        </member>
                        <member>
                           <name>group</name>
                           <value>
                              <string>lp-se</string>
                           </value>
                        </member>
                        <member>
                           <name>name</name>
                           <value>
                              <string>lp-se_1</string>
                           </value>
                        </member>
                        <member>
                           <name>statename</name>
                           <value>
                              <string>RUNNING</string>
                           </value>
                        </member>
                        <member>
                           <name>start</name>
                           <value>
                              <int>1519310284</int>
                           </value>
                        </member>
                        <member>
                           <name>state</name>
                           <value>
                              <int>20</int>
                           </value>
                        </member>
                        <member>
                           <name>stdout_logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.out.log</string>
                           </value>
                        </member>
                     </struct>
                  </value>
                  <value>
                     <struct>
                        <member>
                           <name>description</name>
                           <value>
                              <string>pid 30801, uptime 0:02:39</string>
                           </value>
                        </member>
                        <member>
                           <name>pid</name>
                           <value>
                              <int>30801</int>
                           </value>
                        </member>
                        <member>
                           <name>stderr_logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.err.log</string>
                           </value>
                        </member>
                        <member>
                           <name>stop</name>
                           <value>
                              <int>1519310265</int>
                           </value>
                        </member>
                        <member>
                           <name>logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.out.log</string>
                           </value>
                        </member>
                        <member>
                           <name>exitstatus</name>
                           <value>
                              <int>0</int>
                           </value>
                        </member>
                        <member>
                           <name>spawnerr</name>
                           <value>
                              <string />
                           </value>
                        </member>
                        <member>
                           <name>now</name>
                           <value>
                              <int>1519310425</int>
                           </value>
                        </member>
                        <member>
                           <name>group</name>
                           <value>
                              <string>lp-se</string>
                           </value>
                        </member>
                        <member>
                           <name>name</name>
                           <value>
                              <string>lp-se_10</string>
                           </value>
                        </member>
                        <member>
                           <name>statename</name>
                           <value>
                              <string>RUNNING</string>
                           </value>
                        </member>
                        <member>
                           <name>start</name>
                           <value>
                              <int>1519310266</int>
                           </value>
                        </member>
                        <member>
                           <name>state</name>
                           <value>
                              <int>20</int>
                           </value>
                        </member>
                        <member>
                           <name>stdout_logfile</name>
                           <value>
                              <string>/var/log/supervisord/lp-se.out.log</string>
                           </value>
                        </member>
                     </struct>
                  </value>
               </data>
            </array>
         </value>
      </param>
   </params>
</methodResponse>

The result that I would like to see: count total amount of structures and separately, amount of structures, where the "state" member have value 20.


Solution

  • I have found the answer by oneself. There is my example below:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <xmlrpc.h>
    #include <xmlrpc_client.h>
    
    #define NAME       "Supervisor XML-RPC client"
    #define VERSION    "0.1"
    #define SERVER_URL "http://127.0.0.1:9001/RPC2"
    
    void die_if_fault_occurred (xmlrpc_env *env)
    {
        /* Check our error-handling environment for an XML-RPC fault. */
        if (env->fault_occurred) {
            fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
                    env->fault_string, env->fault_code);
            exit(1);
        }
    }
    
    int main (int argc, char** argv)
    {
        xmlrpc_env env;
        xmlrpc_value *result = NULL;
        unsigned int quotientCt = 0;
        unsigned long long int total_process = 0ULL;
        unsigned long long int correct_statename_count = 0ULL;
    
        /* Start up our XML-RPC client library. */
        xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION);
        xmlrpc_env_init(&env);
    
        /* Call our XML-RPC server. */
        result = xmlrpc_client_call(&env, SERVER_URL,"supervisor.getAllProcessInfo","()");
    
        die_if_fault_occurred(&env);
    
        /* Parse our result value. */
        total_process = xmlrpc_array_size(&env, result);
    
        for (unsigned long long int i = 0; i < total_process; i++) {
            xmlrpc_value * array_elementP;
    
            char *description;
            int pid;
            char *stderr_logfile;
            int stop;
            char *logfile;
            int exitstatus;
            char *spawnerr;
            int now;
            char *group;
            char *name;
            char *statename;
            int *start;
            int state;
            char *stdout_logfile;
    
            xmlrpc_array_read_item(&env, result, i, &array_elementP);
    
            xmlrpc_decompose_value(&env, array_elementP,
                                   "{s:s,s:i,s:s,s:i,s:s,s:i,s:s,s:i,s:s,s:s,s:s,s:i,s:i,s:s,*}",
                                   "description", &description,
                                   "pid",&pid,
                                   "stderr_logfile",&stderr_logfile,
                                   "stop",&stop,
                                   "logfile",&logfile,
                                   "exitstatus",&exitstatus,
                                   "spawnerr",&spawnerr,
                                   "now",&now,
                                   "group",&group,
                                   "name",&name,
                                   "statename",&statename,
                                   "start",&start,
                                   "state",&state,
                                   "stdout_logfile",&stdout_logfile
                                  );
    
            char correct_statename[] = "RUNNING";
    
            if (strncmp(statename, correct_statename,sizeof(correct_statename))==0) {
                correct_statename_count++;
            }
    
    #if 1
            printf("description:%s",description);
            printf(" pid:%d",pid);
            printf(" stderr_logfile:%s",stderr_logfile);
            printf(" stop:%lld",stop);
            printf(" logfile:%s",logfile);
            printf(" exitstatus:%d",exitstatus);
            printf(" spawnerr:%s",spawnerr);
            printf(" now:%d",now);
            printf(" group:%s",group);
            printf(" name:%s",name);
            printf(" statename:%s",statename);
            printf(" start:%d",start);
            printf(" state:%d",state);
            printf(" stdout_logfile:%s ",stdout_logfile);
            printf("\n");
    #endif
            die_if_fault_occurred(&env);
    
            /* Dispose of our result value. */
            xmlrpc_DECREF(array_elementP);
        }
    
        /* Dispose of our result value. */
        xmlrpc_DECREF(result);
    
        /* Shutdown our XML-RPC client library. */
        xmlrpc_env_clean(&env);
        xmlrpc_client_cleanup();
    
        printf("total_process:%llu; correct_statename_count:%llu;\n",total_process,correct_statename_count);
    
        return 0;
    }