Skip to content

Commit a10e6f5

Browse files
Options argument in Xslt class constructor. (#59)
* Escape option in `Xslt` object, to turn off XML escape if needed. * Updating README.md.
1 parent 38d1030 commit a10e6f5

File tree

9 files changed

+63
-25
lines changed

9 files changed

+63
-25
lines changed

.eslintrc.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ module.exports = {
175175
'no-whitespace-before-property': 'error',
176176
'no-with': 'error',
177177
'nonblock-statement-body-position': 'error',
178-
'object-curly-newline': 'error',
179178
'object-property-newline': 'error',
180179
'object-shorthand': 'error',
181180
'one-var': 'off',

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,19 @@ const xPath = new XPath();
5959

6060
If you write pre-2015 JS code, make adjustments as needed.
6161

62+
### `Xslt` class options
63+
64+
You can pass an `options` object to `Xslt` class:
65+
66+
```js
67+
const options = {
68+
escape: false
69+
};
70+
const xslt = new Xslt(options);
71+
```
72+
73+
- `escape` (`boolean`, default `true`): replaces symbols like `<`, `>`, `&` and `"` by the corresponding [XML entities](https://www.tutorialspoint.com/xml/xml_character_entities.htm).
74+
6275
### Direct use in browsers
6376

6477
You can simply add a tag like this:

src/dom/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './functions';
22
export * from './xdocument';
33
export * from './xml-functions';
4+
export * from './xml-output-options';
45
export * from './xnode';

src/dom/xml-functions.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import { domGetAttributeValue } from './functions';
1313
import { XNode } from './xnode';
1414
import { XDocument } from './xdocument';
15+
import { XmlOutputOptions } from './xml-output-options';
1516

1617
// Returns the text value of a node; for nodes without children this
1718
// is the nodeValue, for nodes with children this is the concatenation
@@ -145,29 +146,35 @@ function xmlTextRecursive(node: XNode, buf: any[], cdata: any) {
145146

146147
/**
147148
* Returns the representation of a node as XML text.
148-
* @param node The starting node.
149-
* @param opt_cdata If using CDATA configuration.
149+
* @param {XNode} node The starting node.
150+
* @param {XmlOutputOptions} options XML output options.
150151
* @returns The XML string.
151152
*/
152-
export function xmlTransformedText(node: XNode, opt_cdata: boolean = false) {
153+
export function xmlTransformedText(
154+
node: XNode,
155+
options: XmlOutputOptions = {
156+
cData: false,
157+
escape: true
158+
}
159+
) {
153160
const buffer = [];
154-
xmlTransformedTextRecursive(node, buffer, opt_cdata);
161+
xmlTransformedTextRecursive(node, buffer, options);
155162
return buffer.join('');
156163
}
157164

158-
function xmlTransformedTextRecursive(node: XNode, buffer: any[], cdata: boolean) {
165+
function xmlTransformedTextRecursive(node: XNode, buffer: any[], options: XmlOutputOptions) {
159166
if (node.printed) return;
160167
const nodeType = node.transformedNodeType || node.nodeType;
161168
const nodeValue = node.transformedNodeValue || node.nodeValue;
162169
if (nodeType == DOM_TEXT_NODE) {
163170
if (node.transformedNodeValue && node.transformedNodeValue.trim() !== '') {
164-
const finalText = node.escape ?
171+
const finalText = node.escape && options.escape?
165172
xmlEscapeText(node.transformedNodeValue) :
166173
node.transformedNodeValue;
167174
buffer.push(finalText);
168175
}
169176
} else if (nodeType == DOM_CDATA_SECTION_NODE) {
170-
if (cdata) {
177+
if (options.cData) {
171178
buffer.push(nodeValue);
172179
} else {
173180
buffer.push(`<![CDATA[${nodeValue}]]>`);
@@ -179,15 +186,15 @@ function xmlTransformedTextRecursive(node: XNode, buffer: any[], cdata: boolean)
179186
// had transformations, children should be present at output.
180187
// This is called here "muted logic".
181188
if (node.transformedNodeName !== null && node.transformedNodeName !== undefined) {
182-
xmlElementLogicTrivial(node, buffer, cdata);
189+
xmlElementLogicTrivial(node, buffer, options);
183190
} else {
184-
xmlElementLogicMuted(node, buffer, cdata);
191+
xmlElementLogicMuted(node, buffer, options);
185192
}
186193
} else if (nodeType == DOM_DOCUMENT_NODE || nodeType == DOM_DOCUMENT_FRAGMENT_NODE) {
187194
const childNodes = node.transformedChildNodes.concat(node.childNodes);
188-
// const childNodes = node.transformedChildNodes.length > 0 ? node.transformedChildNodes : node.childNodes;
195+
189196
for (let i = 0; i < childNodes.length; ++i) {
190-
xmlTransformedTextRecursive(childNodes[i], buffer, cdata);
197+
xmlTransformedTextRecursive(childNodes[i], buffer, options);
191198
}
192199
}
193200

@@ -200,7 +207,7 @@ function xmlTransformedTextRecursive(node: XNode, buffer: any[], cdata: boolean)
200207
* @param buffer The XML buffer.
201208
* @param cdata If using CDATA configuration.
202209
*/
203-
function xmlElementLogicTrivial(node: XNode, buffer: any[], cdata: boolean) {
210+
function xmlElementLogicTrivial(node: XNode, buffer: any[], options: XmlOutputOptions) {
204211
buffer.push(`<${xmlFullNodeName(node)}`);
205212

206213
const attributes = node.transformedAttributes || node.attributes;
@@ -223,7 +230,7 @@ function xmlElementLogicTrivial(node: XNode, buffer: any[], cdata: boolean) {
223230
} else {
224231
buffer.push('>');
225232
for (let i = 0; i < childNodes.length; ++i) {
226-
xmlTransformedTextRecursive(childNodes[i], buffer, cdata);
233+
xmlTransformedTextRecursive(childNodes[i], buffer, options);
227234
}
228235
buffer.push(`</${xmlFullNodeName(node)}>`);
229236
}
@@ -237,10 +244,10 @@ function xmlElementLogicTrivial(node: XNode, buffer: any[], cdata: boolean) {
237244
* @param buffer The XML buffer.
238245
* @param cdata If using CDATA configuration.
239246
*/
240-
function xmlElementLogicMuted(node: XNode, buffer: any[], cdata: boolean) {
247+
function xmlElementLogicMuted(node: XNode, buffer: any[], options: XmlOutputOptions) {
241248
const childNodes = node.transformedChildNodes.length > 0 ? node.transformedChildNodes : node.childNodes;
242249
for (let i = 0; i < childNodes.length; ++i) {
243-
xmlTransformedTextRecursive(childNodes[i], buffer, cdata);
250+
xmlTransformedTextRecursive(childNodes[i], buffer, options);
244251
}
245252
}
246253

src/dom/xml-output-options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export type XmlOutputOptions = {
2+
cData: boolean;
3+
escape: boolean;
4+
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export { XPath } from './xpath';
2-
export { Xslt } from './xslt';
2+
export { Xslt, XsltOptions } from './xslt';
33
export { xmlParse, xmlEscapeText } from './dom';
44
export { ExprContext } from './xpath';

src/xslt/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './xslt-options';
2+
export * from './xslt';

src/xslt/xslt-options.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type XsltOptions = {
2+
escape: boolean
3+
}

src/xslt.ts renamed to src/xslt/xslt.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import {
2727
xmlTransformedText,
2828
xmlValue,
2929
xmlValue2
30-
} from './dom';
31-
import { ExprContext, XPath } from './xpath';
30+
} from '../dom';
31+
import { ExprContext, XPath } from '../xpath';
3232

3333
import {
3434
DOM_ATTRIBUTE_NODE,
@@ -38,10 +38,11 @@ import {
3838
DOM_DOCUMENT_NODE,
3939
DOM_ELEMENT_NODE,
4040
DOM_TEXT_NODE
41-
} from './constants';
42-
import { Expression } from './xpath/expressions/expression';
43-
import { StringValue, NodeSetValue } from './xpath/values';
44-
import { LocationExpr } from './xpath/expressions';
41+
} from '../constants';
42+
import { Expression } from '../xpath/expressions/expression';
43+
import { StringValue, NodeSetValue } from '../xpath/values';
44+
import { LocationExpr } from '../xpath/expressions';
45+
import { XsltOptions } from './xslt-options';
4546

4647
/**
4748
* The main class for XSL-T processing. The implementation is NOT
@@ -69,11 +70,13 @@ import { LocationExpr } from './xpath/expressions';
6970
*/
7071
export class Xslt {
7172
xPath: XPath;
73+
options: XsltOptions;
7274
outputMethod: string;
7375
outputOmitXmlDeclaration: string;
7476

75-
constructor() {
77+
constructor(options: XsltOptions = { escape: true }) {
7678
this.xPath = new XPath();
79+
this.options = options
7780
this.outputMethod = "xml";
7881
this.outputOmitXmlDeclaration = "no";
7982
}
@@ -97,7 +100,13 @@ export class Xslt {
97100
}
98101

99102
this.xsltProcessContext(expressionContext, stylesheet, output, parameters);
100-
const ret = xmlTransformedText(output);
103+
const ret = xmlTransformedText(
104+
output,
105+
{
106+
cData: false,
107+
escape: this.options.escape
108+
}
109+
);
101110
return ret;
102111
}
103112

0 commit comments

Comments
 (0)