diff --git a/src/xpath/lib b/src/xpath/lib
index 5ec18e4..1e9b871 160000
--- a/src/xpath/lib
+++ b/src/xpath/lib
@@ -1 +1 @@
-Subproject commit 5ec18e4561f754e78d94d0dc6a3c12b020230c64
+Subproject commit 1e9b871bd6b328fa4a130d5b4c0088adc842ed93
diff --git a/tests/xslt/arithmetic.test.ts b/tests/xslt/arithmetic.test.ts
new file mode 100644
index 0000000..b574ab6
--- /dev/null
+++ b/tests/xslt/arithmetic.test.ts
@@ -0,0 +1,133 @@
+import { Xslt, XmlParser } from '../../src/index';
+
+describe('XPath arithmetic operations', () => {
+ let xslt: Xslt;
+ let xmlParser: XmlParser;
+
+ beforeEach(() => {
+ xslt = new Xslt();
+ xmlParser = new XmlParser();
+ });
+
+ it('addition: number + 1 returns 2', async () => {
+ const xml = xmlParser.xmlParse('1');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('2');
+ });
+
+ it('subtraction: number - 1 returns 0', async () => {
+ const xml = xmlParser.xmlParse('1');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('0');
+ });
+
+ it('multiplication: number * 2 returns 2', async () => {
+ const xml = xmlParser.xmlParse('1');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('2');
+ });
+
+ it('division: number div 2 returns 5', async () => {
+ const xml = xmlParser.xmlParse('10');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('5');
+ });
+
+ it('modulo: number mod 3 returns 1', async () => {
+ const xml = xmlParser.xmlParse('10');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('1');
+ });
+
+ it('node + node: first + second returns correct sum', async () => {
+ const xml = xmlParser.xmlParse('34');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('7');
+ });
+
+ it('decimal node: price * 2 returns 7', async () => {
+ const xml = xmlParser.xmlParse('3.5');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('7');
+ });
+
+ it('attribute node: @value + 1 returns 6', async () => {
+ const xml = xmlParser.xmlParse(' ');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('6');
+ });
+
+ it('unary negation on node: -number returns -5', async () => {
+ const xml = xmlParser.xmlParse('5');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('-5');
+ });
+
+ it('empty node-set in arithmetic does not throw', async () => {
+ // XPath 1.0 typically yields NaN for arithmetic on an empty node-set.
+ // This test only asserts that xsltProcess resolves without throwing.
+ const xml = xmlParser.xmlParse('1');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ await xslt.xsltProcess(xml, stylesheet);
+ });
+
+ it('plain number select still works: select="number" returns 1', async () => {
+ const xml = xmlParser.xmlParse('1');
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+ const result = await xslt.xsltProcess(xml, stylesheet);
+ expect(result).toBe('1');
+ });
+});
diff --git a/tests/xslt/copy-of.test.tsx b/tests/xslt/copy-of.test.tsx
index 56098cd..5384712 100644
--- a/tests/xslt/copy-of.test.tsx
+++ b/tests/xslt/copy-of.test.tsx
@@ -1,9 +1,48 @@
import assert from 'assert';
-import { XmlParser } from '../../src/dom';
-import { Xslt } from '../../src/xslt';
+import { Xslt, XmlParser } from '../../src/index';
describe('xsl:copy-of', () => {
+ it('keeps comment content stable across repeated identity transforms', async () => {
+ const xslt = new Xslt();
+ const xmlParser = new XmlParser();
+
+ const xmlInput = '';
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+
+ const firstInputDoc = xmlParser.xmlParse(xmlInput);
+ const firstPass = await xslt.xsltProcess(firstInputDoc, stylesheet);
+ assert.equal(firstPass, xmlInput);
+
+ const secondInputDoc = xmlParser.xmlParse(firstPass);
+ const secondPass = await xslt.xsltProcess(secondInputDoc, stylesheet);
+ assert.equal(secondPass, firstPass);
+ });
+
+ it('keeps empty comments stable across repeated identity transforms', async () => {
+ const xslt = new Xslt();
+ const xmlParser = new XmlParser();
+
+ const xmlInput = '';
+ const stylesheet = xmlParser.xmlParse(`
+
+
+
+`);
+
+ const firstInputDoc = xmlParser.xmlParse(xmlInput);
+ const firstPass = await xslt.xsltProcess(firstInputDoc, stylesheet);
+ assert.equal(firstPass, xmlInput);
+
+ const secondInputDoc = xmlParser.xmlParse(firstPass);
+ const secondPass = await xslt.xsltProcess(secondInputDoc, stylesheet);
+ assert.equal(secondPass, firstPass);
+ });
+
it('Trivial', async () => {
const xmlSource = `
diff --git a/tests/xslt/issue-187.test.ts b/tests/xslt/issue-187.test.ts
deleted file mode 100644
index f95cc46..0000000
--- a/tests/xslt/issue-187.test.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { Xslt, XmlParser } from '../../src/index';
-
-describe('Issue #187: Identity transformation adds spaces to comments', () => {
- it('keeps comment content stable across repeated identity transforms', async () => {
- const xslt = new Xslt();
- const xmlParser = new XmlParser();
-
- const xmlInput = '';
- const stylesheet = xmlParser.xmlParse(`
-
-
-
-`);
-
- const firstInputDoc = xmlParser.xmlParse(xmlInput);
- const firstPass = await xslt.xsltProcess(firstInputDoc, stylesheet);
- expect(firstPass).toBe(xmlInput);
-
- const secondInputDoc = xmlParser.xmlParse(firstPass);
- const secondPass = await xslt.xsltProcess(secondInputDoc, stylesheet);
- expect(secondPass).toBe(firstPass);
- });
-
- it('keeps empty comments stable across repeated identity transforms', async () => {
- const xslt = new Xslt();
- const xmlParser = new XmlParser();
-
- const xmlInput = '';
- const stylesheet = xmlParser.xmlParse(`
-
-
-
-`);
-
- const firstInputDoc = xmlParser.xmlParse(xmlInput);
- const firstPass = await xslt.xsltProcess(firstInputDoc, stylesheet);
- expect(firstPass).toBe(xmlInput);
-
- const secondInputDoc = xmlParser.xmlParse(firstPass);
- const secondPass = await xslt.xsltProcess(secondInputDoc, stylesheet);
- expect(secondPass).toBe(firstPass);
- });
-});
\ No newline at end of file
diff --git a/tests/xslt/issue-183.test.ts b/tests/xslt/template-match.test.ts
similarity index 74%
rename from tests/xslt/issue-183.test.ts
rename to tests/xslt/template-match.test.ts
index 0aea773..5a6c0b1 100644
--- a/tests/xslt/issue-183.test.ts
+++ b/tests/xslt/template-match.test.ts
@@ -1,47 +1,43 @@
import { Xslt, XmlParser } from '../../src/index';
-describe('Issue #183: Template match with nested elements', () => {
- it('should match //message when nested under ', async () => {
- const xslt = new Xslt();
- const xmlParser = new XmlParser();
+describe('xsl:template match patterns', () => {
+ let xslt: Xslt;
+ let xmlParser: XmlParser;
+ beforeEach(() => {
+ xslt = new Xslt();
+ xmlParser = new XmlParser();
+ });
+
+ it('matches //message when nested under a child element', async () => {
const xml = xmlParser.xmlParse('Hello World.');
const stylesheet = xmlParser.xmlParse(`
`);
-
const result = await xslt.xsltProcess(xml, stylesheet);
expect(result).toBe('Hello World.
');
});
- it('should match with explicit path /page/child/message', async () => {
- const xslt = new Xslt();
- const xmlParser = new XmlParser();
-
+ it('matches with explicit absolute path /page/child/message', async () => {
const xml = xmlParser.xmlParse('Hello World.');
const stylesheet = xmlParser.xmlParse(`
`);
-
const result = await xslt.xsltProcess(xml, stylesheet);
expect(result).toBe('Hello World.
');
});
- it('should match //message when NOT nested (direct child of root)', async () => {
- const xslt = new Xslt();
- const xmlParser = new XmlParser();
-
+ it('matches //message when element is a direct child of root', async () => {
const xml = xmlParser.xmlParse('Hello World.');
const stylesheet = xmlParser.xmlParse(`
`);
-
const result = await xslt.xsltProcess(xml, stylesheet);
expect(result).toBe('Hello World.
');
});