Convert xml to key-value pair notation

前端 未结 2 1289
醉梦人生
醉梦人生 2021-02-09 09:59

I use xmlstarlet el -v to display the structure of an xml file, including all the attributes and values. I would like to convert its output to some sort of key-valu

2条回答
  •  既然无缘
    2021-02-09 10:01

    I decided to write a small program using libxml2, which parses the XML and recursively outputs it in the desired format.

    The code can be compiled using the following command, or something similar (I decided to call it xmlkv, kv standing for key-value):

    cc -o xmlkv xmlkv.c -s -Os -Wall -Wextra `xml2-config --cflags --libs`
    

    The code:

    #include 
    #include 
    #include 
    #include 
    
    static void print_elements(xmlNode *);
    
    static void
    print_elements(xmlNode *node)
    {
        xmlNode *n;
        xmlAttrPtr a;
        xmlChar *v, *p, *q;
    
        for (n = node; n; n = n->next) {
            if (n->type == XML_ELEMENT_NODE) {
                if ((p = xmlGetNodePath(n)) == NULL)
                    return;
    
                for (q = p; *q; q++)
                    if (*q == '/')
                        *q = '.';
    
                for (a = n->properties; a; a = a->next) {
                    if ((v = xmlGetProp(n, a->name)) == NULL)
                        return;
    
                    printf("%s.%s=%s\n", p + 1, a->name, v);
                    xmlFree(v);
                }
    
                xmlFree(p);
            }
    
            print_elements(n->children);
        }
    }
    
    int
    main(int argc, char **argv)
    {
        xmlDoc *doc = NULL;
        xmlNode *root = NULL;
    
        LIBXML_TEST_VERSION
    
        if (argc != 2) {
            fprintf(stderr, "usage: %s \n", *argv);
            return EXIT_FAILURE;
        }
    
        if ((doc = xmlReadFile(argv[1], NULL, 0)) == NULL)
            return EXIT_FAILURE;
    
        if ((root = xmlDocGetRootElement(doc)) == NULL)
            return EXIT_FAILURE;
    
        print_elements(root);
    
        xmlFreeDoc(doc);
        xmlCleanupParser();
    
        return EXIT_SUCCESS;
    }
    

    A test:

    $ cat test.xml
    
    
    
    
    
    
    
    
    
    
    $ ./xmlkv test.xml
    commSyslog.descr=Syslog Service
    commSyslog.name=syslog
    commSyslog.policyOwner=local
    commSyslog.severity=critical
    commSyslog.commSyslogClient[1].adminState=disabled
    commSyslog.commSyslogClient[1].forwardingFacility=local7
    commSyslog.commSyslogClient[1].hostname=none
    commSyslog.commSyslogClient[1].name=secondary
    commSyslog.commSyslogClient[1].severity=critical
    commSyslog.commSyslogClient[2].adminState=disabled
    commSyslog.commSyslogClient[2].forwardingFacility=local7
    commSyslog.commSyslogClient[2].hostname=none
    commSyslog.commSyslogClient[2].name=tertiary
    commSyslog.commSyslogClient[2].severity=critical
    commSyslog.commSyslogClient[3].adminState=disabled
    commSyslog.commSyslogClient[3].forwardingFacility=local7
    commSyslog.commSyslogClient[3].hostname=none
    commSyslog.commSyslogClient[3].name=primary
    commSyslog.commSyslogClient[3].severity=critical
    commSyslog.commSyslogMonitor.adminState=disabled
    commSyslog.commSyslogMonitor.descr=
    commSyslog.commSyslogMonitor.name=
    commSyslog.commSyslogMonitor.severity=critical
    commSyslog.commSyslogConsole.adminState=disabled
    commSyslog.commSyslogConsole.descr=
    commSyslog.commSyslogConsole.name=
    commSyslog.commSyslogConsole.severity=critical
    commSyslog.commSyslogSource.audits=disabled
    commSyslog.commSyslogSource.descr=
    commSyslog.commSyslogSource.events=disabled
    commSyslog.commSyslogSource.faults=enabled
    commSyslog.commSyslogSource.name=
    commSyslog.commSyslogFile.adminState=enabled
    commSyslog.commSyslogFile.descr=
    commSyslog.commSyslogFile.name=messages
    commSyslog.commSyslogFile.severity=critical
    commSyslog.commSyslogFile.size=4194304
    

    Seems nice, just what I wanted. Of course, replacing / with . is pretty much useless, but I prefer this notation since it's better on the eyes.

提交回复
热议问题