Skip to content

Commit 8d401d2

Browse files
committed
Fix. Timing of 'start_document'
1 parent 11daa78 commit 8d401d2

File tree

5 files changed

+32
-19
lines changed

5 files changed

+32
-19
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ When using in SAX style, create an instance of the parser and register the liste
1212
The XML to be parsed is specified by Deno.Reader, UINT8 array, or a character string.
1313

1414
```typescript
15-
import { SAXParser } from 'https://denopkg.com/m-kur/xmlp@v0.10/mod.ts';
15+
import { SAXParser } from 'https://denopkg.com/masataka/xmlp@v0.11/mod.ts';
1616

1717
// create a SAX parser instance
1818
const parser = new SAXParser();
@@ -59,7 +59,7 @@ I think it's more interesting to write the Pull style than the SAX. This Pull pa
5959
Currently the Pull parser supports Uint8 arrays and strings, not Deno.Reader.
6060

6161
```typeScript
62-
import { PullParser } from 'https://denopkg.com/m-kur/xmlp@v0.10/mod.ts';
62+
import { PullParser } from 'https://denopkg.com/masataka/xmlp@v0.11/mod.ts';
6363

6464
// create a pull parser instance
6565
const parser = new PullParser();

handler.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ function isWhitespace(c: string): boolean {
99

1010
// BEFORE_DOCUMENT; FOUND_LT, Error
1111
export function handleBeforeDocument(cx: XMLParseContext, c: string): XMLParseEvent[] {
12-
let events: XMLParseEvent[] = [];
1312
if (c === '<') {
14-
events = [['start_document']];
1513
cx.state = 'FOUND_LT';
1614
} else {
1715
if (!isWhitespace(c)) {
1816
throw new XMLParseError('Non-whitespace before document.', cx);
1917
}
2018
}
21-
return events;
19+
return [];
2220
}
2321

2422
// GENERAL_STUFF; FOUND_LT
@@ -86,7 +84,7 @@ export function handleProcInstEnding(cx: XMLParseContext, c: string): XMLParseEv
8684
if (c === '>') {
8785
events = [['processing_instruction', cx.memento]];
8886
cx.clearMemento();
89-
cx.state = 'GENERAL_STUFF';
87+
cx.state = cx.elementLength > 0 ? 'GENERAL_STUFF' : 'BEFORE_DOCUMENT';
9088
} else {
9189
cx.appendMemento(`?${c}`);
9290
cx.state = 'PROC_INST';
@@ -113,7 +111,7 @@ export function handleSgmlDecl(cx: XMLParseContext, c: string): XMLParseEvent[]
113111
} else if (c === '>') {
114112
events = [['sgml_declaration', cx.memento]];
115113
cx.clearMemento();
116-
cx.state = 'GENERAL_STUFF';
114+
cx.state = cx.elementLength > 0 ? 'GENERAL_STUFF' : 'BEFORE_DOCUMENT';
117115
} else {
118116
cx.appendMemento(c);
119117
}
@@ -197,13 +195,13 @@ export function handleCommentEnding2(cx: XMLParseContext, c: string): XMLParseEv
197195
return events;
198196
}
199197

200-
// DOCTYPE; doctype & GENERAL_STUFF
198+
// DOCTYPE; doctype & BEFORE_DOCUMENT
201199
export function handleDoctype(cx: XMLParseContext, c: string): XMLParseEvent[] {
202200
let events: XMLParseEvent[] = [];
203201
if (c === '>') {
204202
events = [['doctype', cx.memento]];
205203
cx.clearMemento();
206-
cx.state = 'GENERAL_STUFF';
204+
cx.state = 'BEFORE_DOCUMENT';
207205
} else {
208206
cx.appendMemento(c);
209207
}
@@ -212,6 +210,9 @@ export function handleDoctype(cx: XMLParseContext, c: string): XMLParseEvent[] {
212210

213211
function emitStartElement(cx: XMLParseContext): XMLParseEvent[] {
214212
const events: XMLParseEvent[] = [];
213+
if (cx.elementLength === 1) {
214+
events.push(['start_document']);
215+
}
215216
const element = cx.peekElement()!;
216217
for (const { ns, uri } of element.prefixMappings) {
217218
cx.registerNamespace(ns, uri);

handler_test.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,13 @@ Deno.test('handleProcInst', () => {
7070

7171
Deno.test('handleProcInstEnding', () => {
7272
const cx = new XMLParseContext();
73-
// processing_instruction & GENERAL_STUFF
73+
// processing_instruction & BEFORE_DOCUMENT
7474
cx.state = 'PROC_INST_ENDING';
7575
cx.appendMemento('test');
7676
const [[event, procInst]] = handler.handleProcInstEnding(cx, '>');
7777
assertEquals(event, 'processing_instruction');
7878
assertEquals(procInst, 'test');
79-
assertEquals(cx.state, 'GENERAL_STUFF');
79+
assertEquals(cx.state, 'BEFORE_DOCUMENT');
8080
// stay
8181
cx.state = 'PROC_INST_ENDING';
8282
cx.appendMemento('test');
@@ -102,13 +102,13 @@ Deno.test('handleSgmlDecl', () => {
102102
cx.appendMemento('DOCTYP');
103103
handler.handleSgmlDecl(cx, 'E');
104104
assertEquals(cx.state, 'DOCTYPE');
105-
// sgml_declaration & GENERAL_STUFF
105+
// sgml_declaration & BEFORE_DOCUMENT
106106
cx.state = 'SGML_DECL';
107107
cx.appendMemento('test');
108108
const [[event, sgml]] = handler.handleSgmlDecl(cx, '>');
109109
assertEquals(event, 'sgml_declaration');
110110
assertEquals(sgml, 'test');
111-
assertEquals(cx.state, 'GENERAL_STUFF');
111+
assertEquals(cx.state, 'BEFORE_DOCUMENT');
112112
assertEquals(cx.memento, '');
113113
// Error
114114
cx.state = 'SGML_DECL';
@@ -204,19 +204,20 @@ Deno.test('handleCommentEnding2', () => {
204204

205205
Deno.test('handleDoctype', () => {
206206
const cx = new XMLParseContext();
207-
// doctype & GENERAL_STUFF
207+
// doctype & BEFORE_DOCUMENT
208208
cx.state = 'DOCTYPE';
209209
cx.appendMemento('tes');
210210
handler.handleDoctype(cx, 't');
211211
const [[event, doctype]] = handler.handleDoctype(cx, '>');
212212
assertEquals(event, 'doctype');
213213
assertEquals(doctype, 'test');
214-
assertEquals(cx.state, 'GENERAL_STUFF');
214+
assertEquals(cx.state, 'BEFORE_DOCUMENT');
215215
});
216216

217217
Deno.test('handleStartTag', () => {
218218
const cx = new XMLParseContext();
219219
// start_element & GENERAL_STUFF
220+
cx.newElement('root');
220221
cx.state = 'START_TAG';
221222
cx.appendMemento('a');
222223
const [[event, element]] = handler.handleStartTag(cx, '>');
@@ -239,6 +240,7 @@ Deno.test('handleStartTag', () => {
239240
Deno.test('handleStartTagStuff', () => {
240241
const cx = new XMLParseContext();
241242
// start_element & GENERAL_STUFF
243+
cx.newElement('root');
242244
cx.state = 'START_TAG_STUFF';
243245
cx.newElement('a');
244246
const [[event, element]] = handler.handleStartTagStuff(cx, '>');
@@ -262,6 +264,7 @@ Deno.test('handleStartTagStuff', () => {
262264
Deno.test('handleEmptyElementTag', () => {
263265
const cx = new XMLParseContext();
264266
// start_element & end_element & GENERAL_STUFF
267+
cx.newElement('root');
265268
cx.state = 'EMPTY_ELEMENT_TAG';
266269
cx.newElement('test');
267270
const [[event0, element0], [event1, element1]] = handler.handleEmptyElementTag(cx, '>');
@@ -322,6 +325,7 @@ Deno.test('handleAttributeEqual', () => {
322325
Deno.test('handleAttributeValueStart', () => {
323326
const cx = new XMLParseContext();
324327
// ATTRIBUTE_VALUE_END
328+
cx.newElement('root');
325329
cx.state = 'ATTRIBUTE_VALUE_START';
326330
cx.newElement('a');
327331
cx.peekElement()!.newAttribute('b');
@@ -343,6 +347,7 @@ Deno.test('handleAttributeValueEnd', () => {
343347
handler.handleAttributeValueEnd(cx, '/');
344348
assertEquals(cx.state, 'EMPTY_ELEMENT_TAG');
345349
// start_element & GENERAL_STUFF
350+
cx.newElement('root');
346351
cx.state = 'ATTRIBUTE_VALUE_END';
347352
cx.newElement('a');
348353
const [[event, element]] = handler.handleAttributeValueEnd(cx, '>');

parser_test.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,15 @@ Deno.test('PullParser', async () => {
106106
const parser = new PullParser();
107107
const file = await Deno.readFile('parser_test.xml');
108108
const events = parser.parse(file);
109-
assertEquals(events.next().value, { name: 'start_document' });
110109
assertEquals(events.next().value, { name: 'processing_instruction', procInst: 'xml version="1.0" encoding="utf-8"' });
110+
assertEquals(events.next().value, { name: 'start_document' });
111+
assertEquals(events.next().value, { name: 'start_prefix_mapping', ns: 'atom', uri: 'http://www.w3.org/2005/Atom' });
112+
assertEquals(events.next().value, { name: 'start_prefix_mapping', ns: 'm', uri: 'https://xmlp.test/m' });
113+
assertEquals((events.next().value as PullResult).element.qName, 'rss');
114+
assertEquals((events.next().value as PullResult).element.qName, 'channel');
115+
assertEquals((events.next().value as PullResult).element.qName, 'title');
116+
assertEquals((events.next().value as PullResult).text, 'XML Parser for Deno');
117+
assertEquals((events.next().value as PullResult).name, 'end_element');
111118
while(true) {
112119
const { done } = events.next();
113120
if (done) {

parser_test.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:m="https://xmlp.test/m">
33
<channel>
4-
<title>SAX Parser for Deno</title>
5-
<description>SAX Parser Library for Deno Stream Writer</description>
4+
<title>XML Parser for Deno</title>
5+
<description>XML Parser Library for Deno Stream Writer</description>
66
<link>https://xmlp.test/m/saxp</link>
77
<atom:link href="https://xmlp.test/m/saxp" rel="self" type="application/rss+xml"/>
88
<lastBuildDate>Sat, 10 Oct 2020 9:00:00 GMT</lastBuildDate>
@@ -12,7 +12,7 @@
1212
<link>https://xmlp.test/m/saxp/2020/10/10/</link>
1313
<guid isPermaLink="false">urn:uuid:12345678-abcd-efgh-ijkl-90mn123opq4r</guid>
1414
<pubDate>Sat, 10 Oct 2020 12:00:00 GMT</pubDate>
15-
<description>SAXPの利用方法と、サンプルコード</description>
15+
<description>SAXParser &anp; PullParser</description>
1616
<m:comment id="0">Good</m:comment>
1717
<m:comment id="1">Bad</m:comment>
1818
<m:comment id="2">Foo</m:comment>

0 commit comments

Comments
 (0)