Skip to content

Commit 1192b9f

Browse files
committed
Added option to parse XML from a string
1 parent f495c58 commit 1192b9f

12 files changed

Lines changed: 107 additions & 23 deletions

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Open source XML library written in TypeScript
44

55
Implements a SAX parser that exposes the these methods from the `ContentHandler` interface:
66

7+
* initialize(): void;
78
* setCatalog(catalog: Catalog): void;
89
* startDocument(): void;
910
* endDocument(): void;
@@ -53,10 +54,16 @@ export class Test {
5354
let contentHandler: ContentHandler = new DOMBuilder();
5455
let xmlParser = new SAXParser();
5556
xmlParser.setContentHandler(contentHandler);
56-
xmlParser.parse("test.xml");
57+
xmlParser.parseFile("test.xml");
5758
let doc: XMLDocument = (contentHandler as DOMBuilder).getDocument();
5859
let root: XMLElement = doc.getRoot();
5960
console.log(root.toString());
61+
62+
// build the document again, this time from a string
63+
xmlParser.parseString(doc.toString());
64+
let newDoc = (contentHandler as DOMBuilder).getDocument();
65+
console.log(newDoc.getRoot().toString());
66+
6067
} catch (error: any) {
6168
if (error instanceof Error) {
6269
console.log(error.message);

build.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
rm -rf dist/
2+
rm -rf node_modules/
3+
rm package-lock.json
4+
npm install
5+
npm run build

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "typesxml",
33
"productName": "TypesXML",
4-
"version": "1.1.0",
4+
"version": "1.2.0",
55
"description": "Open source XML library written in TypeScript",
66
"scripts": {
77
"build": "tsc"
@@ -22,7 +22,7 @@
2222
"url": "https://github.com/rmraya/TypesXML.git"
2323
},
2424
"devDependencies": {
25-
"@types/node": "^20.9.4",
25+
"@types/node": "^20.10.0",
2626
"typescript": "^5.3.2"
2727
}
2828
}

sonar-project.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
sonar.projectKey=TypesXML
33
# this is the name displayed in the SonarQube UI
44
sonar.projectName=TypesXML
5-
sonar.projectVersion=1.1.0
5+
sonar.projectVersion=1.2.0
66

77
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
88
# Since SonarQube 4.2, this property is optional if sonar.modules is set.

ts/Catalog.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export class Catalog {
5151
let contentHandler: ContentHandler = new DOMBuilder();
5252
let parser: SAXParser = new SAXParser();
5353
parser.setContentHandler(contentHandler);
54-
parser.parse(catalogFile);
54+
parser.parseFile(catalogFile);
5555
let catalogDocument: XMLDocument = (contentHandler as DOMBuilder).getDocument();
5656
let catalogRoot: XMLElement = catalogDocument.getRoot();
5757
if (catalogRoot.getName() !== 'catalog') {
@@ -245,8 +245,7 @@ export class Catalog {
245245

246246
matchSystem(systemId: string): string {
247247
if (systemId) {
248-
for (let i: number = 0; i < this.systemRewrites.length; i++) {
249-
let pair: string[] = this.systemRewrites[i];
248+
for (let pair of this.systemRewrites) {
250249
if (systemId.startsWith(pair[0])) {
251250
systemId = pair[1] + systemId.substring(pair[0].length);
252251
}

ts/ContentHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { XMLAttribute } from "./XMLAttribute";
1515

1616
export interface ContentHandler {
1717

18+
initialize(): void;
1819
setCatalog(catalog: Catalog): void;
1920

2021
startDocument(): void;

ts/DOMBuilder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class DOMBuilder implements ContentHandler {
2020
catalog: Catalog;
2121
grammarUrl: string;
2222

23-
constructor() {
23+
initialize(): void {
2424
this.document = new XMLDocument();
2525
this.stack = new Array();
2626
this.inCdData = false;

ts/FileReader.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
* Maxprograms - initial API and implementation
1111
*******************************************************************************/
1212

13-
import { openSync, readSync, closeSync, statSync, Stats } from "fs";
13+
import { Stats, closeSync, openSync, readSync, statSync } from "fs";
14+
import { XMLReader } from "./XMLReader";
1415

15-
export class FileReader {
16+
export class FileReader implements XMLReader {
1617

1718
fileHandle: number;
1819
encoding: BufferEncoding;

ts/SAXParser.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@
1212

1313
import { ContentHandler } from "./ContentHandler";
1414
import { FileReader } from "./FileReader";
15+
import { StringReader } from "./StringReader";
1516
import { XMLAttribute } from "./XMLAttribute";
17+
import { XMLReader } from "./XMLReader";
1618
import { XMLUtils } from "./XMLUtils";
1719

1820
export class SAXParser {
1921

2022
contentHandler: ContentHandler;
21-
reader: FileReader;
23+
reader: XMLReader;
2224
pointer: number;
2325
buffer: string;
24-
fileSize: number;
25-
encoding: BufferEncoding;
2626
elementStack: number;
2727
characterRun: string;
2828
rootParsed: boolean;
@@ -38,11 +38,26 @@ export class SAXParser {
3838
this.contentHandler = contentHandler;
3939
}
4040

41-
parse(path: string, encoding?: BufferEncoding): void {
42-
this.encoding = encoding ? encoding : FileReader.detectEncoding(path);
41+
parseFile(path: string, encoding?: BufferEncoding): void {
42+
if (!this.contentHandler) {
43+
throw new Error('ContentHandler not set');
44+
}
45+
if (!encoding) {
46+
encoding = FileReader.detectEncoding(path);
47+
}
4348
this.reader = new FileReader(path, encoding);
44-
this.fileSize = this.reader.getFileSize();
4549
this.buffer = this.reader.read();
50+
this.contentHandler.initialize();
51+
this.readDocument();
52+
}
53+
54+
parseString(string: string): void {
55+
if (!this.contentHandler) {
56+
throw new Error('ContentHandler not set');
57+
}
58+
this.reader = new StringReader(string);
59+
this.buffer = this.reader.read();
60+
this.contentHandler.initialize();
4661
this.readDocument();
4762
}
4863

ts/StringReader.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2023 Maxprograms.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse License 1.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/org/documents/epl-v10.html
8+
*
9+
* Contributors:
10+
* Maxprograms - initial API and implementation
11+
*******************************************************************************/
12+
import { XMLReader } from "./XMLReader";
13+
14+
export class StringReader implements XMLReader {
15+
16+
CHUNK_SIZE: number = 4096;
17+
18+
data: string;
19+
position: number;
20+
21+
constructor(data: string) {
22+
this.data = data;
23+
this.position = 0;
24+
}
25+
26+
dataAvailable(): boolean {
27+
return this.position < this.data.length;
28+
}
29+
30+
read(): string {
31+
let amount: number = this.CHUNK_SIZE;
32+
if (this.position + this.CHUNK_SIZE > this.data.length) {
33+
amount = this.data.length - this.position;
34+
}
35+
let result: string = this.data.substring(this.position, amount);
36+
this.position += amount;
37+
return result;
38+
}
39+
40+
}

0 commit comments

Comments
 (0)