-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathxslt.c
185 lines (156 loc) · 4.17 KB
/
xslt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <libexslt/exslt.h>
#include <libxml/parser.h>
#include <libxml/xmlversion.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include "xslt.h"
/*
* Function: apply_style
* ----------------------------
* Restyle an XML document using a parsed XSL stylesheet.
*
* style: parsed XSL stylesheet
* xml: XML to be transformed
* params: parameters to be passed
* xml_txt: output from the transform
* xml_txt_len: length in bytes of output
*
* returns 0 if the transform is successful or -1 in case of error
*/
int apply_style(xsltStylesheetPtr style, const char *xml, const char **params,
char **xml_txt, size_t *xml_txt_len) {
int ok;
size_t len;
xmlChar *xml_output;
xmlDocPtr xml_doc, result;
// avoid overflow on conversion from size_t to int
len = strlen(xml);
if (len > INT32_MAX) {
return -1;
}
// parse the provided xml document
xml_doc = xmlParseMemory(xml, (int)strlen(xml));
if (xml_doc == NULL) {
xmlResetLastError();
return -1;
}
const xmlError *error = xmlGetLastError();
if (error) {
xmlResetLastError();
if (error->level > XML_ERR_WARNING) {
return -1;
}
}
// obtain the result from transforming xml_doc using the style
result = xsltApplyStylesheet(style, xml_doc, params);
if (result == NULL) {
xmlFreeDoc(xml_doc);
return -1;
}
// save the transformation result
ok = xsltSaveResultToString(&xml_output, (int *)xml_txt_len, result, style);
if (ok == 0 && *xml_txt_len > 0) {
*xml_txt = malloc(*xml_txt_len);
strncpy(*xml_txt, (const char *)xml_output, *xml_txt_len);
xmlFree(xml_output);
}
xmlFreeDoc(xml_doc);
xmlFreeDoc(result);
return ok;
}
/*
* Function: free_style
* ----------------------------
* Free memory allocated by the style.
* Note that the stylesheet document (style_doc) is also automatically
* freed. See: http://xmlsoft.org/XSLT/html/libxslt-xsltInternals.html
* @ #xsltParseStylesheetDoc.
*
* style: an XSL stylesheet pointer
*
* returns void
*/
void free_style(xsltStylesheetPtr *style) { xsltFreeStylesheet(*style); }
/*
* Function: make_style
* ----------------------------
* Parse an XSL stylesheet.
*
* xsl: XSL to be transformed
* style: parse XSL stylesheet
*
* returns 0 if parsing is successful or -1 in case of error
*/
int make_style(const char *xsl, xsltStylesheetPtr *style) {
size_t len;
xmlDocPtr style_doc;
len = strlen(xsl);
if (len > INT32_MAX) {
return -1;
}
style_doc = xmlParseMemory(xsl, (int)len);
if (style_doc == NULL || xmlGetLastError()) {
xmlResetLastError();
return -1;
}
*style = xsltParseStylesheetDoc(style_doc);
if (*style == NULL || (*style)->errors) {
xmlFreeDoc(style_doc);
return -1;
}
return 0;
}
/*
* Function: xslt
* ----------------------------
* Transforms an XML document using an XSL stylesheet.
*
* xsl: the stylesheet to be used
* xml: the document to transform
* params: parameters to be passed
* xml_txt: output from the transform
* xml_txt_len: length in bytes of output
*
* returns 0 if the transform is successful or -1 in case of error
*/
int xslt(const char *xsl, const char *xml, const char **params, char **xml_txt,
size_t *xml_txt_len) {
int ok;
xsltStylesheetPtr style;
ok = make_style(xsl, &style);
if (ok < 0) {
return -1;
}
ok = apply_style(style, xml, params, xml_txt, xml_txt_len);
free_style(&style);
return ok;
}
/*
* Function: init_exslt
* ----------------------------
* Calls exsltRegisterAll() to enable exsl namespace at templates
*/
void init_exslt() {
LIBXML_TEST_VERSION
xmlInitParser();
xsltInit();
exsltRegisterAll();
}
const char **make_param_array(int num_tuples) {
const char **a = calloc(sizeof(char *), 2 * num_tuples + 1);
a[2 * num_tuples] = NULL;
return a;
}
void set_param(char **a, char *n, char *v, int t) {
a[2 * t] = n;
a[2 * t + 1] = v;
}
void free_param_array(char **a, int num_tuples) {
int i;
for (i = 0; i < 2 * num_tuples; i++)
free(a[i]);
free(a);
}