-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSWXSLTransform.m
More file actions
117 lines (82 loc) · 3.08 KB
/
SWXSLTransform.m
File metadata and controls
117 lines (82 loc) · 3.08 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
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
//
// SWXSLTransform.m
// This file is part of the "SWXMLMapping" project, and is distributed under the MIT License.
//
// Created by Samuel Williams on 23/02/12.
// Copyright (c) 2012 Samuel Williams. All rights reserved.
//
#import "SWXSLTransform.h"
#include <libxslt/xslt.h>
#include <libxslt/documents.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <libexslt/exslt.h>
@implementation SWXSLTransform
+ (void)initialize {
// Ensure that entities are substituted correctly:
xmlSubstituteEntitiesDefault(1);
// Ensure that external entity subsets are loaded:
xmlLoadExtDtdDefaultValue = 1;
// Register all supported external modules:
exsltRegisterAll();
// Register xslt test modules (???)
//xsltRegisterTestModule();
}
@synthesize baseURL = _baseURL;
- (void) releaseStylesheet {
if (_stylesheet) {
xsltFreeStylesheet((xsltStylesheetPtr)_stylesheet);
_stylesheet = NULL;
}
}
- (void) loadStylesheetFromURL:(NSURL *)stylesheetURL {
[self releaseStylesheet];
if (stylesheetURL) {
NSAssert(stylesheetURL.isFileURL, @"Stylesheet URL was not a local file!");
NSData * stylesheetData = [NSData dataWithContentsOfURL:stylesheetURL];
xmlDocPtr stylesheetXMLDocument = xmlParseMemory(stylesheetData.bytes, (int)stylesheetData.length);
NSAssert(stylesheetXMLDocument != NULL, @"Could not load stylesheet: %@", stylesheetURL);
_stylesheet = xsltParseStylesheetDoc(stylesheetXMLDocument);
if (_stylesheet == NULL) {
// We are going to blow up, so free the unreferenced document:
xmlFreeDoc(stylesheetXMLDocument);
}
NSAssert(_stylesheet != NULL, @"Could not parse stylesheet: %@", stylesheetURL);
}
}
- (instancetype)initWithURL:(NSURL *)url {
self = [super init];
if (self) {
self.baseURL = url;
[self loadStylesheetFromURL:url];
}
return self;
}
- (void)dealloc
{
[self releaseStylesheet];
}
- (NSData *) processDocument:(NSString *)xmlBuffer arguments:(NSDictionary *)arguments {
NSAssert(_stylesheet != NULL, @"Stylesheet is NULL");
const char ** parameters = (const char **)malloc(2 * sizeof(const char *) * (arguments.count + 1));
NSUInteger parameterOffset = 0;
for (NSString * key in arguments) {
parameters[parameterOffset] = key.UTF8String;
parameters[parameterOffset+1] = ((NSString *)arguments[key]).UTF8String;
parameterOffset += 2;
}
parameters[parameterOffset] = NULL;
xmlDocPtr sourceDocument = xmlParseMemory(xmlBuffer.UTF8String, [xmlBuffer lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
xmlDocPtr processedDocument = xsltApplyStylesheet((xsltStylesheetPtr)_stylesheet, sourceDocument, parameters);
xmlOutputBufferPtr outputBuffer = xmlAllocOutputBuffer(NULL);
xsltSaveResultTo(outputBuffer, processedDocument, (xsltStylesheetPtr)_stylesheet);
const xmlChar * contents = xmlOutputBufferGetContent(outputBuffer);
size_t size = xmlOutputBufferGetSize(outputBuffer);
NSData * result = [[NSData alloc] initWithBytes:contents length:size];
xmlOutputBufferClose(outputBuffer);
xmlFreeDoc(sourceDocument);
xmlFreeDoc(processedDocument);
free(parameters);
return result;
}
@end