gnu: Add kafs-client
[jackhill/guix/guix.git] / gnu / packages / patches / libxslt-generated-ids.patch
CommitLineData
c74c7c13
ML
1This makes generated IDs deterministic.
2
3Written by Daniel Veillard.
4
5This should be fixed in next release (2.29).
6See https://bugzilla.gnome.org/show_bug.cgi?id=751621.
7
8diff --git a/libxslt/functions.c b/libxslt/functions.c
9index 6448bde..5b00a6d 100644
10--- a/libxslt/functions.c
11+++ b/libxslt/functions.c
12@@ -651,6 +651,63 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
13 }
14
15 /**
16+ * xsltCleanupIds:
17+ * @ctxt: the transformation context
18+ * @root: the root of the resulting document
19+ *
20+ * This clean up ids which may have been saved in Element contents
21+ * by xsltGenerateIdFunction() to provide stable IDs on elements.
22+ *
23+ * Returns the number of items cleaned or -1 in case of error
24+ */
25+int
26+xsltCleanupIds(xsltTransformContextPtr ctxt, xmlNodePtr root) {
27+ xmlNodePtr cur;
28+ int count = 0;
29+
30+ if ((ctxt == NULL) || (root == NULL))
31+ return(-1);
32+ if (root->type != XML_ELEMENT_NODE)
33+ return(-1);
34+
35+ cur = root;
36+ while (cur != NULL) {
37+ if (cur->type == XML_ELEMENT_NODE) {
38+ if (cur->content != NULL) {
39+ cur->content = NULL;
40+ count++;
41+ }
42+ if (cur->children != NULL) {
43+ cur = cur->children;
44+ continue;
45+ }
46+ }
47+ if (cur->next != NULL) {
48+ cur = cur->next;
49+ continue;
50+ }
51+ do {
52+ cur = cur->parent;
53+ if (cur == NULL)
54+ break;
55+ if (cur == (xmlNodePtr) root) {
56+ cur = NULL;
57+ break;
58+ }
59+ if (cur->next != NULL) {
60+ cur = cur->next;
61+ break;
62+ }
63+ } while (cur != NULL);
64+ }
65+
66+fprintf(stderr, "Attributed %d IDs for element, cleaned up %d\n",
67+ ctxt->nextid, count);
68+
69+ return(count);
70+}
71+
72+/**
73 * xsltGenerateIdFunction:
74 * @ctxt: the XPath Parser context
75 * @nargs: the number of arguments
76@@ -701,7 +758,39 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
77 if (obj)
78 xmlXPathFreeObject(obj);
79
80- val = (long)((char *)cur - (char *)&base_address);
81+ /*
82+ * Try to provide stable ID for generated document:
83+ * - usually ID are computed to be placed on elements via attributes
84+ * so using the element as the node for the ID
85+ * - the cur->content should be a correct placeholder for this, we use
86+ * it to hold element node numbers in xmlXPathOrderDocElems to
87+ * speed up XPath too
88+ * - xsltCleanupIds() clean them up before handing the XSLT output
89+ * to the API client.
90+ * - other nodes types use the node address method but that should
91+ * not end up in resulting document ID
92+ * - we can enable this by default without risk of performance issues
93+ * only the one pass xsltCleanupIds() is added
94+ */
95+ if (cur->type == XML_ELEMENT_NODE) {
96+ if (cur->content == NULL) {
97+ xsltTransformContextPtr tctxt;
98+
99+ tctxt = xsltXPathGetTransformContext(ctxt);
100+ if (tctxt == NULL) {
101+ val = (long)((char *)cur - (char *)&base_address);
102+ } else {
103+ tctxt->nextid++;
104+ val = tctxt->nextid;
105+ cur->content = (void *) (val);
106+ }
107+ } else {
108+ val = (long) cur->content;
109+ }
110+ } else {
111+ val = (long)((char *)cur - (char *)&base_address);
112+ }
113+
114 if (val >= 0) {
115 sprintf((char *)str, "idp%ld", val);
116 } else {
117diff --git a/libxslt/functions.h b/libxslt/functions.h
118index e0e0bf9..4a1e163 100644
119--- a/libxslt/functions.h
120+++ b/libxslt/functions.h
121@@ -64,6 +64,13 @@ XSLTPUBFUN void XSLTCALL
122 int nargs);
123
124 /*
125+ * Cleanup for ID generation
126+ */
127+XSLTPUBFUN int XSLTCALL
128+ xsltCleanupIds (xsltTransformContextPtr ctxt,
129+ xmlNodePtr root);
130+
131+/*
132 * And the registration
133 */
134
135diff --git a/libxslt/transform.c b/libxslt/transform.c
136index 24f9eb2..2bdf6bf 100644
137--- a/libxslt/transform.c
138+++ b/libxslt/transform.c
139@@ -700,6 +700,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
140 cur->traceCode = (unsigned long*) &xsltDefaultTrace;
141 cur->xinclude = xsltGetXIncludeDefault();
142 cur->keyInitLevel = 0;
143+ cur->nextid = 0;
144
145 return(cur);
146
147@@ -6092,6 +6093,13 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
148 if (root != NULL) {
149 const xmlChar *doctype = NULL;
150
151+ /*
152+ * cleanup ids which may have been saved in Elements content ptrs
153+ */
154+ if (ctxt->nextid != 0) {
155+ xsltCleanupIds(ctxt, root);
156+ }
157+
158 if ((root->ns != NULL) && (root->ns->prefix != NULL))
159 doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name);
160 if (doctype == NULL)
161diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
162index 95e8fe6..8eedae4 100644
163--- a/libxslt/xsltInternals.h
164+++ b/libxslt/xsltInternals.h
badcb119 165@@ -1782,6 +1782,8 @@ struct _xsltTransformContext {
c74c7c13 166 int maxTemplateVars;
badcb119
MB
167 unsigned long opLimit;
168 unsigned long opCount;
c74c7c13
ML
169+
170+ unsigned long nextid;/* for generating stable ids */
171 };
172
173 /**