[xml] [PATCH 6/6] When sorting, also do DOCTYPE contents.
- From: Adam Spragg <adam spra gg>
- To: xml gnome org
- Cc: Adam Spragg <adam spra gg>
- Subject: [xml] [PATCH 6/6] When sorting, also do DOCTYPE contents.
- Date: Tue, 5 Oct 2010 22:22:28 +0100
Puts a "canonical" order on XML_ELEMENT_DECL, XML_ATTRIBUTE_DECL and
XML_ENTITY_DECL nodes.
---
xmlsave.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 115 insertions(+), 28 deletions(-)
diff --git a/xmlsave.c b/xmlsave.c
index 5e9d1eb..e298559 100644
--- a/xmlsave.c
+++ b/xmlsave.c
@@ -525,6 +525,33 @@ xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
}
/**
+ * xmlStrPrefixCmp:
+ * @prea: Prefix for first string
+ * @a: First string
+ * @preb: Prefix for second string
+ * @b: Second string
+ *
+ * Compare two strings with prefixes, similar to strcmp(3). Strings with
+ * NULL prefixes sort before strings with non-NULL prefixes.
+ */
+static int
+xmlStrPrefixCmp(xmlChar const * prea, xmlChar const * a, xmlChar const * preb, xmlChar const * b)
+{
+ int i;
+ if ((prea != NULL)
+ && (preb == NULL))
+ return +1;
+ if ((preb != NULL)
+ && (prea == NULL))
+ return -1;
+ if ((prea != NULL)
+ && (preb != NULL)
+ && (i = strcmp((char const *) prea, (char const *) preb)) != 0)
+ return i;
+ return strcmp((char const *) a, (char const *) b);
+}
+
+/**
* xmlNsPtrCmp:
* @a: pointer to first xmlNsPtr to compare
* @b: pointer to second xmlNsPtr to compare
@@ -538,19 +565,7 @@ xmlNsPtrCmp(void const * a, void const * b)
{
xmlNsPtr x = *((xmlNsPtr *) a);
xmlNsPtr y = *((xmlNsPtr *) b);
- int i;
- if ((x->prefix != NULL)
- && (y->prefix == NULL))
- return +1;
- if ((y->prefix != NULL)
- && (x->prefix == NULL))
- return -1;
- if ((x->prefix != NULL)
- && (y->prefix != NULL)
- && (i = strcmp((char const *) x->prefix,
- (char const *) y->prefix)) != 0)
- return i;
- return strcmp((char const *) x->href, (char const *) y->href);
+ return xmlStrPrefixCmp(x->prefix, x->href, y->prefix, y->href);
}
/**
@@ -720,19 +735,8 @@ xmlAttrPtrCmp(void const * a, void const * b)
{
xmlAttrPtr x = *((xmlAttrPtr *) a);
xmlAttrPtr y = *((xmlAttrPtr *) b);
- int i;
- if ((x->ns != NULL) && (x->ns->prefix != NULL)
- && ((y->ns == NULL) || (y->ns->prefix == NULL)))
- return +1;
- if ((y->ns != NULL) && (y->ns->prefix != NULL)
- && ((x->ns == NULL) || (x->ns->prefix == NULL)))
- return -1;
- if ((x->ns != NULL) && (x->ns->prefix != NULL)
- && (y->ns != NULL) && (y->ns->prefix != NULL)
- && (i = strcmp((char const *) x->ns->prefix,
- (char const *) y->ns->prefix)) != 0)
- return i;
- return strcmp((char const *) x->name, (char const *) y->name);
+ return xmlStrPrefixCmp(x->ns != NULL ? x->ns->prefix : NULL, x->name,
+ y->ns != NULL ? y->ns->prefix : NULL, y->name);
}
/**
@@ -802,6 +806,56 @@ xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
/**
+ * xmlNodePtrCmp:
+ * @a: pointer to first xmlNodePtr to compare
+ * @b: pointer to second xmlNodePtr to compare
+ *
+ * Compare two xmlNodePtrs whose order in XML documents does not matter, as for
+ * qsort(3). This includes nodes of type XML_ELEMENT_DECL, XML_ATTRIBUTE_DECL
+ * and XML_ENTITY_DECL, to put them in that order, and then order each type
+ * by name.
+ */
+static int
+xmlNodePtrCmp(void const * a, void const * b)
+{
+ xmlNodePtr x = *((xmlNodePtr *) a);
+ xmlNodePtr y = *((xmlNodePtr *) b);
+
+ if (x->type != y->type) {
+ if (x->type == XML_ELEMENT_DECL)
+ return -1;
+ if (y->type == XML_ELEMENT_DECL)
+ return +1;
+ if (x->type == XML_ATTRIBUTE_DECL)
+ return -1;
+ if (y->type == XML_ATTRIBUTE_DECL)
+ return +1;
+ if (x->type == XML_ENTITY_DECL)
+ return -1;
+ if (y->type == XML_ENTITY_DECL)
+ return +1;
+ }
+
+ if (x->type == XML_ELEMENT_DECL) {
+ xmlElementPtr ex = (xmlElementPtr) x;
+ xmlElementPtr ey = (xmlElementPtr) y;
+ return xmlStrPrefixCmp(ex->prefix, ex->name, ey->prefix, ey->name);
+ }
+ else if (x->type == XML_ATTRIBUTE_DECL) {
+ xmlAttributePtr ax = (xmlAttributePtr) x;
+ xmlAttributePtr ay = (xmlAttributePtr) y;
+ return xmlStrPrefixCmp(ax->prefix, ax->name, ay->prefix, ay->name);
+ }
+ else if (x->type == XML_ENTITY_DECL) {
+ xmlEntityPtr ex = (xmlEntityPtr) x;
+ xmlEntityPtr ey = (xmlEntityPtr) y;
+ return strcmp((char const *) ex->name, (char const *) ey->name);
+ }
+
+ return 0;
+}
+
+/**
* xmlNodeDumpOutputInternalFormatted
* @ctxt: the context to dump to
* @cur: the node to dump
@@ -837,8 +891,41 @@ static void
xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
if (cur == NULL) return;
while (cur != NULL) {
- xmlNodeDumpOutputInternalFormatted(ctxt, cur);
- cur = cur->next;
+ if ((ctxt->options & XML_SAVE_SORT) &&
+ ((cur->type == XML_ELEMENT_DECL) ||
+ (cur->type == XML_ATTRIBUTE_DECL) ||
+ (cur->type == XML_ENTITY_DECL)))
+ {
+ int n;
+ int i;
+ xmlNodePtr node;
+ xmlNodePtr next;
+
+ n = 0;
+ for (node = cur;
+ node != NULL &&
+ ((node->type == XML_ELEMENT_DECL) ||
+ (node->type == XML_ATTRIBUTE_DECL) ||
+ (node->type == XML_ENTITY_DECL));
+ node = node->next)
+ {
+ ++n;
+ }
+ next = node;
+ xmlNodePtr nodes[n];
+ for (node = cur, i = 0; i < n; node = node->next, ++i) {
+ nodes[i] = node;
+ }
+ qsort(nodes, n, sizeof(nodes[0]), xmlNodePtrCmp);
+ for (i = 0; i < n; ++i) {
+ xmlNodeDumpOutputInternalFormatted(ctxt, nodes[i]);
+ }
+ cur = next;
+ }
+ else {
+ xmlNodeDumpOutputInternalFormatted(ctxt, cur);
+ cur = cur->next;
+ }
}
}
--
1.7.1
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]