Skip to content

Commit f06a049

Browse files
- Moving DOM-specific functions out of utils.ts;
- Not exposing all the methods of `Xslt` class.
1 parent 02afad9 commit f06a049

File tree

6 files changed

+81
-86
lines changed

6 files changed

+81
-86
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
"url": "git+https://github.com/DesignLiquido/xslt-processor.git"
2222
},
2323
"keywords": [
24-
"xslt"
24+
"xslt",
25+
"xpath",
26+
"xml"
2527
],
2628
"author": "Johannes Wilm",
2729
"contributors": [

src/dom/functions.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,6 @@ import he from 'he';
1212
import { DOM_ELEMENT_NODE } from "../constants";
1313

1414
import {
15-
domSetAttribute,
16-
domAppendChild,
17-
domCreateTextNode,
18-
domCreateElement,
19-
domCreateCDATASection,
20-
domCreateComment,
2115
namespaceMapAt
2216
} from './util';
2317
import { XDocument } from "./xdocument";
@@ -29,13 +23,47 @@ import {
2923
XML11_NAME,
3024
XML11_ATTRIBUTE
3125
} from './xmltoken';
26+
import { XNode } from './xnode';
3227

3328
const XML10_TAGNAME_REGEXP = new RegExp(`^(${XML10_NAME})`);
3429
const XML10_ATTRIBUTE_REGEXP = new RegExp(XML10_ATTRIBUTE, 'g');
3530

3631
const XML11_TAGNAME_REGEXP = new RegExp(`^(${XML11_NAME})`);
3732
const XML11_ATTRIBUTE_REGEXP = new RegExp(XML11_ATTRIBUTE, 'g');
3833

34+
// Wrapper around DOM methods so we can condense their invocations.
35+
export function domGetAttribute(node: any, name: any) {
36+
return node.getAttribute(name);
37+
}
38+
39+
export function domSetAttribute(node: any, name: any, value: any) {
40+
return node.setAttribute(name, value);
41+
}
42+
43+
export function domAppendChild(node: XNode, child: any) {
44+
return node.appendChild(child);
45+
}
46+
47+
export function domCreateTextNode(doc: any, text: any) {
48+
return doc.createTextNode(text);
49+
}
50+
51+
export function domCreateElement(doc: any, name: any) {
52+
return doc.createElement(name);
53+
}
54+
55+
export function domCreateCDATASection(doc: any, data: any) {
56+
return doc.createCDATASection(data);
57+
}
58+
59+
export function domCreateComment(doc: any, text: any) {
60+
return doc.createComment(text);
61+
}
62+
63+
export function domCreateDocumentFragment(doc: XDocument) {
64+
return doc.createDocumentFragment();
65+
}
66+
3967
// Traverses the element nodes in the DOM section underneath the given
4068
// node and invokes the given callbacks as methods on every element
4169
// node encountered. Function opt_pre is invoked before a node's

src/dom/util.ts

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from '../constants';
2020
import { FunctionCallExpr, BinaryExpr, UnaryMinusExpr, NumberExpr } from '../xpath/expressions';
2121
import { XDocument } from './xdocument';
22+
import { XNode } from './xnode';
2223

2324
// Throws an exception if false.
2425
export function assert(b) {
@@ -200,45 +201,12 @@ function xmlEscapeAttr(s) {
200201
* @param {Node} node
201202
* @return {Document}
202203
*/
203-
export function xmlOwnerDocument(node) {
204+
export function xmlOwnerDocument(node: any) {
204205
if (node.nodeType == DOM_DOCUMENT_NODE) {
205206
return node;
206-
} else {
207-
return node.ownerDocument;
208207
}
209-
}
210-
211-
// Wrapper around DOM methods so we can condense their invocations.
212-
export function domGetAttribute(node: any, name: any) {
213-
return node.getAttribute(name);
214-
}
215-
216-
export function domSetAttribute(node: any, name: any, value: any) {
217-
return node.setAttribute(name, value);
218-
}
219-
220-
export function domAppendChild(node: any, child: any) {
221-
return node.appendChild(child);
222-
}
223-
224-
export function domCreateTextNode(doc: any, text: any) {
225-
return doc.createTextNode(text);
226-
}
227-
228-
export function domCreateElement(doc: any, name: any) {
229-
return doc.createElement(name);
230-
}
231-
232-
export function domCreateCDATASection(doc: any, data: any) {
233-
return doc.createCDATASection(data);
234-
}
235-
236-
export function domCreateComment(doc: any, text: any) {
237-
return doc.createComment(text);
238-
}
239208

240-
export function domCreateDocumentFragment(doc: XDocument) {
241-
return doc.createDocumentFragment();
209+
return node.ownerDocument;
242210
}
243211

244212
/**

src/dom/xnode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export class XNode {
9292
return new XNode(type, name, value, owner, namespace);
9393
}
9494

95-
appendChild(node) {
95+
appendChild(node: any) {
9696
// firstChild
9797
if (this.childNodes.length == 0) {
9898
this.firstChild = node;

src/xslt.ts

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,19 @@
3535
// Original author: Steffen Meschkat <mesch@google.com>
3636
import he from 'he';
3737

38+
import { xmlValue, xmlText, xmlOwnerDocument } from './dom/util';
3839
import {
39-
xmlValue,
40-
xmlText,
41-
xmlOwnerDocument,
42-
domGetAttribute,
43-
domSetAttribute,
40+
XDocument,
41+
XNode,
4442
domAppendChild,
45-
domCreateTextNode,
46-
domCreateElement,
4743
domCreateCDATASection,
4844
domCreateComment,
49-
domCreateDocumentFragment
50-
} from './dom/util';
51-
import { XDocument, XNode } from './dom';
45+
domCreateDocumentFragment,
46+
domCreateElement,
47+
domCreateTextNode,
48+
domGetAttribute,
49+
domSetAttribute
50+
} from './dom';
5251
import { ExprContext, XPath } from './xpath';
5352

5453
import {
@@ -98,7 +97,7 @@ export class Xslt {
9897
* @param output the root of the generated output, as DOM node.
9998
* @param _parameters Extra parameters.
10099
*/
101-
xsltProcessContext(input: any, template: XNode, output: any, _parameters?: any) {
100+
protected xsltProcessContext(input: ExprContext, template: XNode, output: XNode, _parameters?: any) {
102101
const outputDocument = xmlOwnerDocument(output);
103102

104103
if (!this.isXsltElement(template)) {
@@ -157,9 +156,9 @@ export class Xslt {
157156
}
158157
}
159158
for (let j = 0; j < sortContext.contextSize(); ++j) {
160-
const nj = sortContext.nodelist[j];
159+
const nodeAtJ = sortContext.nodelist[j];
161160
for (let i = 0; i < templates.length; ++i) {
162-
this.xsltProcessContext(sortContext.clone(nj, j), templates[i], output);
161+
this.xsltProcessContext(sortContext.clone(nodeAtJ, j), templates[i], output);
163162
}
164163
}
165164
break;
@@ -315,7 +314,7 @@ export class Xslt {
315314
* @param input TODO
316315
* @param template TODO
317316
*/
318-
xsltWithParam(input: any, template: any) {
317+
protected xsltWithParam(input: any, template: any) {
319318
for (const c of template.childNodes) {
320319
if (c.nodeType == DOM_ELEMENT_NODE && this.isXsltElement(c, 'with-param')) {
321320
this.xsltVariable(input, c, true);
@@ -332,7 +331,7 @@ export class Xslt {
332331
* @param template TODO
333332
* @todo case-order is not implemented.
334333
*/
335-
xsltSort(input: any, template: any) {
334+
protected xsltSort(input: any, template: any) {
336335
const sort = [];
337336

338337
for (const c of template.childNodes) {
@@ -360,7 +359,7 @@ export class Xslt {
360359
// case. I.e. decides if this is a default value or a local
361360
// value. xsl:variable and xsl:with-param override; xsl:param doesn't.
362361

363-
xsltVariable(input, template, override) {
362+
protected xsltVariable(input, template, override) {
364363
const name = this.xmlGetAttribute(template, 'name');
365364
const select = this.xmlGetAttribute(template, 'select');
366365

@@ -384,7 +383,7 @@ export class Xslt {
384383
// Implements xsl:chose and its child nodes xsl:when and
385384
// xsl:otherwise.
386385

387-
xsltChoose(input, template, output) {
386+
protected xsltChoose(input, template, output) {
388387
for (const childNode of template.childNodes) {
389388
if (childNode.nodeType != DOM_ELEMENT_NODE) {
390389
continue;
@@ -407,7 +406,7 @@ export class Xslt {
407406
* @param template TODO
408407
* @param output TODO
409408
*/
410-
xsltForEach(input, template, output) {
409+
protected xsltForEach(input, template, output) {
411410
const select = this.xmlGetAttribute(template, 'select');
412411
const nodes = this.xPath.xPathEval(select, input).nodeSetValue();
413412
const sortContext = input.clone(nodes[0], 0, nodes);
@@ -422,16 +421,16 @@ export class Xslt {
422421
* Traverses the template node tree. Calls the main processing
423422
* function with the current input context for every child node of the
424423
* current template node.
425-
* @param input Normally the Expression Context.
424+
* @param context Normally the Expression Context.
426425
* @param template The XSL-T definition.
427426
* @param output The XML output.
428427
*/
429-
xsltChildNodes(input: ExprContext, template: any, output: any) {
428+
protected xsltChildNodes(context: ExprContext, template: any, output: XNode) {
430429
// Clone input context to keep variables declared here local to the
431430
// siblings of the children.
432-
const context = input.clone();
431+
const contextClone = context.clone();
433432
for (let i = 0; i < template.childNodes.length; ++i) {
434-
this.xsltProcessContext(context, template.childNodes[i], output);
433+
this.xsltProcessContext(contextClone, template.childNodes[i], output);
435434
}
436435
}
437436

@@ -440,12 +439,12 @@ export class Xslt {
440439
* not specify an XSL-T operation and therefore is appended to the
441440
* output with all its attributes. Then continues traversing the
442441
* template node tree.
443-
* @param input In general the Expression Context.
442+
* @param context The Expression Context.
444443
* @param template The XSLT stylesheet or transformation.
445444
* @param output The output.
446445
* @param outputDocument The output document, if the case.
447446
*/
448-
xsltPassThrough(input: any, template: any, output: any, outputDocument: any) {
447+
protected xsltPassThrough(context: ExprContext, template: any, output: XNode, outputDocument: XDocument) {
449448
if (template.nodeType == DOM_TEXT_NODE) {
450449
if (this.xsltPassText(template)) {
451450
let node = domCreateTextNode(outputDocument, template.nodeValue);
@@ -454,20 +453,18 @@ export class Xslt {
454453
} else if (template.nodeType == DOM_ELEMENT_NODE) {
455454
let node = domCreateElement(outputDocument, template.nodeName);
456455

457-
for (const a of template.attributes) {
458-
if (a) {
459-
const name = a.nodeName;
460-
const value = this.xsltAttributeValue(a.nodeValue, input);
461-
domSetAttribute(node, name, value);
462-
}
456+
for (const attribute of template.attributes.filter((a: any) => a)) {
457+
const name = attribute.nodeName;
458+
const value = this.xsltAttributeValue(attribute.nodeValue, context);
459+
domSetAttribute(node, name, value);
463460
}
464461

465462
domAppendChild(output, node);
466-
this.xsltChildNodes(input, template, node);
463+
this.xsltChildNodes(context, template, node);
467464
} else {
468465
// This applies also to the DOCUMENT_NODE of the XSL stylesheet,
469466
// so we don't have to treat it specially.
470-
this.xsltChildNodes(input, template, output);
467+
this.xsltChildNodes(context, template, output);
471468
}
472469
}
473470

@@ -480,7 +477,7 @@ export class Xslt {
480477
* @todo Whitespace stripping on the input document is
481478
* currently not implemented.
482479
*/
483-
xsltPassText(template: XNode) {
480+
protected xsltPassText(template: XNode) {
484481
if (!template.nodeValue.match(/^\s*$/)) {
485482
return true;
486483
}
@@ -517,7 +514,7 @@ export class Xslt {
517514
* @param context TODO
518515
* @returns TODO
519516
*/
520-
xsltAttributeValue(value: any, context: any) {
517+
protected xsltAttributeValue(value: any, context: any) {
521518
const parts = value.split('{');
522519
if (parts.length == 1) {
523520
return value;
@@ -549,7 +546,7 @@ export class Xslt {
549546
* @param name TODO
550547
* @returns TODO
551548
*/
552-
xmlGetAttribute(node: XNode, name: string) {
549+
protected xmlGetAttribute(node: XNode, name: string) {
553550
// TODO(mesch): This should not be necessary if the DOM is working
554551
// correctly. The DOM is responsible for resolving entities, not the
555552
// application.
@@ -569,7 +566,7 @@ export class Xslt {
569566
* @param {XNode} src the node being copied, part in input document
570567
* @param {XDocument} dstDocument dstDocument
571568
*/
572-
xsltCopyOf(dst: any, src: any, dstDocument: any) {
569+
protected xsltCopyOf(dst: any, src: any, dstDocument: any) {
573570
if (src.nodeType == DOM_DOCUMENT_FRAGMENT_NODE || src.nodeType == DOM_DOCUMENT_NODE) {
574571
for (let i = 0; i < src.childNodes.length; ++i) {
575572
this.xsltCopyOf(dst, src.childNodes[i], dstDocument);
@@ -597,7 +594,7 @@ export class Xslt {
597594
* @param {XDocument} dstDocument dstDocument
598595
* @returns {XNode|Null} If an element node was created, the element node. Otherwise null.
599596
*/
600-
xsltCopy(dst: any, src: any, dstDocument: any) {
597+
protected xsltCopy(dst: any, src: any, dstDocument: any) {
601598
if (src.nodeType == DOM_ELEMENT_NODE) {
602599
let node = domCreateElement(dstDocument, src.nodeName);
603600
domAppendChild(dst, node);
@@ -628,11 +625,11 @@ export class Xslt {
628625
* @param context TODO
629626
* @returns TODO
630627
*/
631-
xsltMatch(match: string, context: ExprContext) {
628+
protected xsltMatch(match: string, context: ExprContext) {
632629
const expr = this.xPath.xPathParse(match);
633630

634631
if (expr.steps.length <= 0) {
635-
throw new Error("Error resolving XSLT match: Location Expression should have steps.");
632+
throw new Error('Error resolving XSLT match: Location Expression should have steps.');
636633
}
637634

638635
const firstStep = expr.steps[0];
@@ -659,7 +656,7 @@ export class Xslt {
659656
return this.relativeXsltMatch(expr, context);
660657
}
661658

662-
absoluteXsltMatch(levels: string[], expr: Expression, context: ExprContext) {
659+
private absoluteXsltMatch(levels: string[], expr: Expression, context: ExprContext) {
663660
const result = expr.evaluate(context.clone(context.node, 0, [context.node])).nodeSetValue();
664661
if (result.length > 0) {
665662
if (result.length === 1) {
@@ -673,7 +670,7 @@ export class Xslt {
673670
return false;
674671
}
675672

676-
relativeXsltMatch(expr: Expression, context: ExprContext) {
673+
private relativeXsltMatch(expr: Expression, context: ExprContext) {
677674
let node = context.node;
678675

679676
while (node) {
@@ -691,7 +688,7 @@ export class Xslt {
691688
}
692689

693690
// Test if the given element is an XSLT element, optionally the one with the given name
694-
isXsltElement(element: any, opt_wantedName?: string) {
691+
protected isXsltElement(element: any, opt_wantedName?: string) {
695692
if (opt_wantedName && element.localName != opt_wantedName) return false;
696693
if (element.namespaceURI) return element.namespaceURI === 'http://www.w3.org/1999/XSL/Transform';
697694
return element.prefix === 'xsl'; // backwards compatibility with earlier versions of xslt-processor

tests/local-name.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import assert from 'assert';
44
import React from 'react';
55
import { dom } from 'isomorphic-jsx';
66

7-
import { xmlParse } from '..'
87
import { Xslt } from '../src/xslt';
8+
import { xmlParse } from '../src/dom/functions';
99

1010
// Just touching the `dom`, otherwise Babel prunes the import.
1111
console.log(dom);

0 commit comments

Comments
 (0)