-
Notifications
You must be signed in to change notification settings - Fork 83
Expand file tree
/
Copy pathxml2_schema.cpp
More file actions
69 lines (51 loc) · 1.85 KB
/
xml2_schema.cpp
File metadata and controls
69 lines (51 loc) · 1.85 KB
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
#include <Rinternals.h>
#include <libxml/xmlerror.h> // xmlError
#include <libxml/xmlschemas.h>
#include <libxml/xmlversion.h> // LIBXML_VERSION
#include <cstddef> // size_t
#include <vector>
#include <string>
#include "xml2_types.h"
#include "xml2_utils.h"
/* * *
* Author: Nick Wellnhofer <wellnhofer@aevum.de>
* Date: Tue, 24 Oct 2023 15:02:36 +0200
* https://github.com/GNOME/libxml2/commit/61034116d0a3c8b295c6137956adc3ae55720711
*
* error: Make more xmlError structs constant
*/
#if defined(LIBXML_VERSION) && (LIBXML_VERSION >= 21200)
void handleSchemaError(void* userData, const xmlError* error) {
#else
void handleSchemaError(void* userData, xmlError* error) {
#endif
std::vector<std::string> * vec = (std::vector<std::string> *) userData;
std::string message = std::string(error->message);
message.resize(message.size() - 1);
vec->push_back(message);
}
// [[export]]
extern "C" SEXP doc_validate(SEXP doc_sxp, SEXP schema_sxp) {
XPtrDoc doc(doc_sxp);
XPtrDoc schema(schema_sxp);
BEGIN_CPP
std::vector<std::string> vec;
xmlSchemaParserCtxtPtr cptr = xmlSchemaNewDocParserCtxt(schema.checked_get());
xmlSchemaSetParserStructuredErrors(cptr, handleSchemaError, &vec);
xmlSchemaPtr sptr = xmlSchemaParse(cptr);
xmlSchemaValidCtxtPtr vptr = xmlSchemaNewValidCtxt(sptr);
xmlSchemaSetValidStructuredErrors(vptr, handleSchemaError, &vec);
SEXP out = PROTECT(Rf_allocVector(LGLSXP, 1));
LOGICAL(out)[0] = xmlSchemaValidateDoc(vptr, doc.checked_get()) == 0;
xmlSchemaFreeParserCtxt(cptr);
xmlSchemaFreeValidCtxt(vptr);
xmlSchemaFree(sptr);
SEXP errors = PROTECT(Rf_allocVector(STRSXP, vec.size()));
for (size_t i = 0; i < vec.size(); ++i) {
SET_STRING_ELT(errors, i, Rf_mkCharLenCE(vec[i].c_str(), vec[i].size(), CE_UTF8));
}
Rf_setAttrib(out, Rf_install("errors"), errors);
UNPROTECT(2);
return out;
END_CPP
}