[xml] [PATCH 4/6] Add xmlSaveOption XML_SAVE_SORT
- From: Adam Spragg <adam spra gg>
- To: xml gnome org
- Cc: Adam Spragg <adam spra gg>
- Subject: [xml] [PATCH 4/6] Add xmlSaveOption XML_SAVE_SORT
- Date: Tue, 5 Oct 2010 22:22:26 +0100
Adds option, initial implementation, and xmllint parameter for use.
---
include/libxml/xmlsave.h | 1 +
xmllint.c | 11 +++++
xmlsave.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 108 insertions(+), 0 deletions(-)
diff --git a/include/libxml/xmlsave.h b/include/libxml/xmlsave.h
index 1669733..737df77 100644
--- a/include/libxml/xmlsave.h
+++ b/include/libxml/xmlsave.h
@@ -35,6 +35,7 @@ typedef enum {
XML_SAVE_AS_XML = 1<<5, /* force XML serialization on HTML doc */
XML_SAVE_AS_HTML = 1<<6, /* force HTML serialization on XML doc */
XML_SAVE_WSNONSIG = 1<<7, /* format with non-significant whitespace */
+ XML_SAVE_SORT = 1<<8, /* sort "unordered" parts of XML, e.g. attrs */
} xmlSaveOption;
diff --git a/xmllint.c b/xmllint.c
index b7af32f..9aef364 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -135,6 +135,7 @@ static int noout = 0;
static int nowrap = 0;
#ifdef LIBXML_OUTPUT_ENABLED
static int format = 0;
+static int sort = 0;
static const char *output = NULL;
static int compress = 0;
static int oldout = 0;
@@ -2661,6 +2662,9 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
else if (format == 2)
saveOpts |= XML_SAVE_WSNONSIG;
+ if (sort == 1)
+ saveOpts |= XML_SAVE_SORT;
+
#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED)
if (xmlout)
saveOpts |= XML_SAVE_AS_XML;
@@ -3020,6 +3024,7 @@ static void usage(const char *name) {
printf("\t 0 Do not pretty print\n");
printf("\t 1 Format the XML content, as --format\n");
printf("\t 2 Add whitespace inside tags, preserving content\n");
+ printf("\t--sort : sort \"unordered\" parts of XML, e.g. attributes\n");
#endif /* LIBXML_OUTPUT_ENABLED */
printf("\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
printf("\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
@@ -3355,6 +3360,12 @@ main(int argc, char **argv) {
xmlKeepBlanksDefault(0);
}
}
+ else if ((!strcmp(argv[i], "-sort")) ||
+ (!strcmp(argv[i], "--sort"))) {
+#ifdef LIBXML_OUTPUT_ENABLED
+ sort = 1;
+#endif
+ }
#ifdef LIBXML_READER_ENABLED
else if ((!strcmp(argv[i], "-stream")) ||
(!strcmp(argv[i], "--stream"))) {
diff --git a/xmlsave.c b/xmlsave.c
index ddf7143..086b31e 100644
--- a/xmlsave.c
+++ b/xmlsave.c
@@ -525,6 +525,35 @@ xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
}
/**
+ * xmlNsPtrCmp:
+ * @a: pointer to first xmlNsPtr to compare
+ * @b: pointer to second xmlNsPtr to compare
+ *
+ * Compare two xmlNsPtrs by the NS prefix/href, as used by qsort.
+ * NSs without prefixes sort before those with, and string comparisons
+ * are done asciibetically, so as to be stable no matter the locale.
+ */
+static int
+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);
+}
+
+/**
* xmlNsDumpOutput:
* @buf: the XML buffer output
* @cur: a namespace
@@ -580,6 +609,25 @@ xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
*/
static void
xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
+ if (ctxt->options & XML_SAVE_SORT) {
+ int n;
+ int i;
+ xmlNsPtr ns;
+
+ n = 0;
+ for (ns = cur; ns != NULL; ns = ns->next) {
+ ++n;
+ }
+ xmlNsPtr nss[n];
+ for (ns = cur, i = 0; ns != NULL; ns = ns->next, ++i) {
+ nss[i] = ns;
+ }
+ qsort(nss, n, sizeof(nss[0]), xmlNsPtrCmp);
+ for (i = 0; i < n; ++i) {
+ xmlNsDumpOutput(ctxt->buf, nss[i], ctxt);
+ }
+ return;
+ }
while (cur != NULL) {
xmlNsDumpOutput(ctxt->buf, cur, ctxt);
cur = cur->next;
@@ -659,6 +707,35 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
}
/**
+ * xmlAttrPtrCmp:
+ * @a: pointer to first xmlAttrPtr to compare
+ * @b: pointer to second xmlAttrPtr to compare
+ *
+ * Compare two xmlAttrPtrs by their name and NS prefix, as used by qsort.
+ * Attrs without NS prefixes sort before those with, and string comparisons
+ * are done asciibetically, so as to be stable no matter the locale.
+ */
+static int
+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);
+}
+
+/**
* xmlAttrDumpOutput:
* @buf: the XML buffer output
* @cur: the attribute pointer
@@ -698,6 +775,25 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
static void
xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
if (cur == NULL) return;
+ if (ctxt->options & XML_SAVE_SORT) {
+ int n;
+ int i;
+ xmlAttrPtr attr;
+
+ n = 0;
+ for (attr = cur; attr != NULL; attr = attr->next) {
+ ++n;
+ }
+ xmlAttrPtr attrs[n];
+ for (attr = cur, i = 0; attr != NULL; attr = attr->next, ++i) {
+ attrs[i] = attr;
+ }
+ qsort(attrs, n, sizeof(attrs[0]), xmlAttrPtrCmp);
+ for (i = 0; i < n; ++i) {
+ xmlAttrDumpOutput(ctxt, attrs[i]);
+ }
+ return;
+ }
while (cur != NULL) {
xmlAttrDumpOutput(ctxt, cur);
cur = cur->next;
--
1.7.1
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]