#include <stdio.h>
+#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
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)
+ {
+ 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 <text>\n", node->name);
+ else if (child->type == XML_CDATA_SECTION_NODE)
+ printf ("%s <cdata>\n", node->name);
+ else if (child->type == XML_COMMENT_NODE)
+ printf ("%s <comment>\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 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 ("<root> %s\n", node->name);
+ 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 = "<text>";
+ else if (child->type == XML_CDATA_SECTION_NODE)
+ name = "<cdata>";
+ else if (child->type == XML_COMMENT_NODE)
+ {
+ name = "<comment>";
+ //printf ("comment %s\n", (char *) child->content);
+ continue;
+ }
+ else
+ name = "<other>";
+
+ 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)
+{
+ 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)
+ {
+ 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_page_setup (xmlNode *node)
+{
+ for (; node; node = node->next)
+ {
+ if (node->name && !strcmp ((char *) node->name, "pageSetup"))
+ return node;
+
+ xmlNode *ps = find_page_setup (node->children);
+ 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)
{
- if (argc != 2)
+ const char *s = (char *) xmlGetProp (root, (xmlChar *) "version");
+ if (!s)
{
- fprintf (stderr, "usage: %s FILE.xml\n", argv[0]);
+ 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]);
}
xmlNode *root = xmlDocGetRootElement(doc);
- print_containment(root);
+
+#if 0
+ /* Limit what we look at to pageSetup node and below. */
+ root = find_page_setup(root);
+ if (!root)
+ return 0;
+ root->next = NULL;
+#endif
+
+ 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 (!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();