X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=parse-xml.c;h=15c4ba2e9bc1c21cb4eb4935304d8c894add1581;hb=refs%2Fheads%2Fspv;hp=c0445052ed017f6ea80111568dc581884c69d4e1;hpb=0f833bb108ef5a1d78be8ee31b2fe2855f6bd03b;p=pspp diff --git a/parse-xml.c b/parse-xml.c index c0445052ed..15c4ba2e9b 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -1,37 +1,276 @@ #include +#include #include #include static void -print_containment (xmlNode * a_node) +print_parents(xmlNode *node) { - for (xmlNode *node = a_node; node; node = node->next) + for (; node; node = node->next) { if (node->type == XML_ELEMENT_NODE) { - const xmlNode *parent = node->parent; - if (parent->type == XML_ELEMENT_NODE) - printf ("%s %s\n", parent->name, node->name); - else if (parent->type == XML_DOCUMENT_NODE) - printf (" %s\n", node->name); + for (xmlNode *child = node->children; child; child = child->next) + { + if (child->type == XML_ELEMENT_NODE) + printf ("%s %s\n", node->name, child->name); + else if (child->type == XML_TEXT_NODE) + printf ("%s \n", node->name); + else if (child->type == XML_CDATA_SECTION_NODE) + printf ("%s \n", node->name); + else if (child->type == XML_COMMENT_NODE) + printf ("%s \n", node->name); + else + printf ("%s <%d>\n", node->name, child->type); + } + } + + print_parents (node->children); + } +} + +static void +print_containment (xmlNode *node) +{ + for (; node; node = node->next) + { + if (node->type == XML_ELEMENT_NODE) + { + const char *child_names[512]; + int child_name_cnt[512]; + int n_names = 0; + for (xmlNode *child = node->children; child; child = child->next) + { + const char *name; + + if (child->type == XML_ELEMENT_NODE) + name = (char *) child->name; + else if (child->type == XML_TEXT_NODE) + name = ""; + else if (child->type == XML_CDATA_SECTION_NODE) + name = ""; + else if (child->type == XML_COMMENT_NODE) + { + name = ""; + //printf ("comment %s\n", (char *) child->content); + continue; + } + else + name = ""; + + for (int i = 0; i < n_names; i++) + if (!strcmp(name, child_names[i])) + { + child_name_cnt[i]++; + goto next; + } + child_names[n_names] = name; + child_name_cnt[n_names] = 1; + n_names++; + + next:; + } + + printf ("%s", node->name); + for (int i = 0; i < n_names; i++) + { + printf (" %s", child_names[i]); + if (child_name_cnt[i] > 1) + printf ("+"); + } + printf ("\n"); } print_containment (node->children); } } -int -main (int argc, char **argv) +static void +print_labels (xmlNode *node) +{ + for (; node; node = node->next) + { + if (node->type == XML_ELEMENT_NODE + && !strcmp((char *) node->name, "label") + && node->parent->type == XML_ELEMENT_NODE + && !strcmp((char *) node->parent->name, "container")) + { + for (xmlNode *child = node->children; child; child = child->next) + if (child->type == XML_TEXT_NODE) + puts ((char *) child->content); + } + + print_labels (node->children); + } +} + +static void +print_attributes (xmlNode * a_node) +{ + for (xmlNode *node = a_node; node; node = node->next) + { + if (node->type == XML_ELEMENT_NODE) + { + printf ("%s", node->name); + for (xmlAttr *attr = node->properties; attr; attr = attr->next) + { + printf (" %s", attr->name); + if (!strcmp ((char *) attr->name, "baseFormat")) + printf ("=%s", (char *) xmlGetProp (node, attr->name)); + } + putchar ('\n'); + } + + print_attributes (node->children); + } +} + +static void +print_string(xmlChar *s) { - if (argc != 2) + for (char *p = (char *) s; *p; p++) + if (*p == '\n') + printf ("\\n"); + else + putchar (*p); +} + +static void +print_cdata (xmlNode * a_node) +{ + for (xmlNode *node = a_node; node; node = node->next) { - fprintf (stderr, "usage: %s FILE.xml\n", argv[0]); + if (node->type == XML_CDATA_SECTION_NODE) + { + print_string (node->content); + putchar ('\n'); + } + + print_cdata (node->children); + } +} + +static void +print_attribute (xmlNode *node, const char *attr) +{ + for (; node; node = node->next) + { + const char *s = (char *) xmlGetProp (node, (xmlChar *) attr); + if (s) + printf ("%s %s=%s\n", node->name, attr, s); + + print_attribute (node->children, attr); + } +} + +static void +print_xml (xmlDoc *doc, xmlNode *node) +{ + xmlBuffer *buf = xmlBufferCreate(); + xmlNodeDump (buf, doc, node, 0, 0); + xmlBufferDump (stdout, buf); + xmlBufferFree (buf); + putchar ('\n'); +} + +static void +print_element (xmlDoc *doc, xmlNode *node, const char *element) +{ + for (; node; node = node->next) + { + if (node->name && !strcmp(element, (char *) node->name)) + print_xml (doc, node); + + print_element (doc, node->children, element); + } +} + +static void +print_id (xmlDoc *doc, xmlNode *node, const char *id) +{ + for (; node; node = node->next) + { + if (node->type == XML_ELEMENT_NODE) + { + const char *node_id = (char *) xmlGetProp (node, (xmlChar *) "id"); + if (node_id && !strcmp (node_id, id)) + { + print_xml (doc, node); + break; + } + } + + print_id (doc, node->children, id); + } +} + +static __attribute__((unused)) xmlNode * +find_node (xmlNode *node, const char *name) +{ + for (; node; node = node->next) + { + if (node->name && !strcmp ((char *) node->name, name)) + return node; + + xmlNode *ps = find_node (node->children, name); + if (ps) + return ps; + } + return NULL; +} + +static void +print_text (xmlNode *node) +{ + for (; node; node = node->next) + { + if (node->type == XML_ELEMENT_NODE) + { + printf ("%s", node->name); + for (xmlNode *child = node->children; child; child = child->next) + if (child->type == XML_TEXT_NODE) + { + putchar (' '); + print_string (child->content); + } + putchar ('\n'); + } + + print_text (node->children); + } +} + +static void +check_version (xmlNode *root, const char *version) +{ + const char *s = (char *) xmlGetProp (root, (xmlChar *) "version"); + if (!s) + { + fprintf (stderr, "missing version\n"); exit (1); } + else if (strcmp(version, s)) + { + exit (0); + } +} + +static void +usage (void) +{ + fprintf (stderr, "usage: parse-xml FILE.xml containment|attributes\n"); + exit (1); +} + +int +main (int argc, char **argv) +{ + if (argc < 3) + usage (); LIBXML_TEST_VERSION; - xmlDoc *doc = xmlReadFile(argv[1], NULL, 0); + xmlDoc *doc = xmlReadFile(argv[1], NULL, XML_PARSE_NOBLANKS); if (doc == NULL) { fprintf (stderr, "error: could not parse file %s\n", argv[1]); @@ -39,7 +278,46 @@ main (int argc, char **argv) } xmlNode *root = xmlDocGetRootElement(doc); - print_containment(root); + + for (int i = 2; i < argc; i++) + { + if (!strcmp(argv[i], "parents")) + print_parents (root); + else if (!strcmp(argv[i], "containment")) + print_containment (root); + else if (!strcmp(argv[i], "attributes")) + print_attributes (root); + else if (!strcmp(argv[i], "cdata")) + print_cdata (root); + else if (!strcmp(argv[i], "text")) + print_text (root); + else if (!strncmp(argv[i], "element:", 8)) + print_element (doc, root, argv[i] + 8); + else if (!strncmp(argv[i], "attr:", 5)) + print_attribute (root, argv[i] + 5); + else if (!strncmp(argv[i], "id:", 3)) + print_id (doc, root, argv[i] + 3); + else if (!strncmp(argv[i], "root:", 5)) + { + /* Limit content to descendants of the given node. */ + root = find_node (root, argv[i] + 5); + if (!root) + return 0; + root->next = NULL; + } + else if (!strncmp(argv[i], "musthave:", 9)) + { + if (!find_node (root, argv[i] + 9)) + return 0; + } + else if (!strcmp(argv[i], "labels")) + print_labels (root); + else if (!strncmp(argv[i], "version=", 8)) + check_version (root, argv[i] + 8); + else + usage (); + } + xmlFreeDoc(doc); xmlCleanupParser();