Skip to content

Commit

Permalink
feat: add forceXMLVersion
Browse files Browse the repository at this point in the history
  • Loading branch information
lddubeau committed Jul 30, 2019
1 parent dae84ff commit 1eedbf8
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 86 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,22 @@ Settings supported:
declaration, then this setting is ignored. Must be `"1.0"` or `"1.1"`. The
default is `"1.0"`.

* `forceXMLVersion` - Boolean. A flag indicating whether to force the XML
version used for parsing to the value of ``defaultXMLVersion``. When this flag
is ``true``, ``defaultXMLVersion`` must be specified. If unspecified, the
default value of this flag is ``false``.

Example: suppose you are parsing a document that has an XML declaration
specifying XML version 1.1.

If you set ``defaultXMLVersion`` to ``"1.0"`` without setting
``forceXMLVersion`` then the XML declaration will override the value of
``defaultXMLVersion`` and the document will be parsed according to XML 1.1.

If you set ``defaultXMLVersion`` to ``"1.0"`` and set ``forceXMLVersion`` to
``true``, then the XML declaration will be ignored and the document will be
parsed according to XML 1.0.

### Methods

`write` - Write bytes onto the stream. You don't have to pass the whole document
Expand Down
13 changes: 12 additions & 1 deletion lib/saxes.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
declare namespace saxes {
export const EVENTS: ReadonlyArray<string>;

export interface SaxesOptions {
export interface CommonSaxesOptions {
xmlns?: boolean;
position?: boolean;
fragment?: boolean;
Expand All @@ -10,6 +10,17 @@ declare namespace saxes {
defaultXMLVersion?: "1.0" | "1.1";
}

export interface NotForced extends CommonSaxesOptions {
forceXMLVersion?: false;
}

export interface Forced extends CommonSaxesOptions {
defaultXMLVersion: CommonSaxesOptions["defaultXMLVersion"];
forceXMLVersion: true;
}

export type SaxesOptions = NotForced | Forced;

export interface XMLDecl {
version?: string;
encoding?: string;
Expand Down
12 changes: 11 additions & 1 deletion lib/saxes.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,11 @@ const FORBIDDEN_BRACKET_BRACKET = 2;
* @property {"1.0" | "1.1"} [defaultXMLVersion] The default XML version to
* use. If unspecified, and there is no XML encoding declaration, the default
* version is "1.0".
*
* @property {boolean} [forceXMLVersion] A flag indicating whether to force the
* XML version used for parsing to the value of ``defaultXMLVersion``. When this
* flag is ``true``, ``defaultXMLVersion`` must be specified. If unspecified,
* the default value of this flag is ``false``.
*/

class SaxesParser {
Expand Down Expand Up @@ -385,7 +390,11 @@ class SaxesParser {
}

let { defaultXMLVersion } = this.opt;
const { forceXMLVersion } = this.opt;
if (defaultXMLVersion === undefined) {
if (forceXMLVersion) {
throw new Error("forceXMLVersion set but defaultXMLVersion is not set");
}
defaultXMLVersion = "1.0";
}
this.setXMLVersion(defaultXMLVersion);
Expand Down Expand Up @@ -1480,7 +1489,8 @@ class SaxesParser {
if (!/^1\.[0-9]+$/.test(version)) {
this.fail("version number must match /^1\\.[0-9]+$/.");
}
else {
// When forceXMLVersion is set, the XML declaration is ignored.
else if (!this.opt.forceXMLVersion) {
this.setXMLVersion(version);
}
break;
Expand Down
220 changes: 136 additions & 84 deletions test/xml-declaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,107 +245,159 @@ describe("xml declaration", () => {
expect(seen).to.be.true;
});

function makeTests(groupName, xmlDeclaration, document, expectedResults) {
function parse(source, options) {
const parser = new saxes.SaxesParser(options);
let error = false;
parser.onerror = () => {
error = true;
};
parser.write(source);
parser.close();
return error;
}

function makeDefaultXMLVersionTests(groupName, xmlDeclaration, document,
expecteUnforcedResults,
expectedForcedResults) {
describe(groupName, () => {
for (const { version, expectError } of expectedResults) {
for (const { version, expectError } of expecteUnforcedResults) {
const errorLabel = expectError ? "errors" : "no errors";
const title = version === undefined ?
`and without defaultXMLVersion: ${errorLabel}` :
`and with defaultXMLVersion === ${version}: ${errorLabel}`;

it(title, () => {
const parser =
new saxes.SaxesParser(version === undefined ? undefined :
{ defaultXMLVersion: version });
let error = false;
parser.onerror = () => {
error = true;
};
parser.write(xmlDeclaration + document);
parser.close();
expect(error).to.equal(expectError);
expect(parse(xmlDeclaration + document,
version === undefined ? undefined :
{ defaultXMLVersion: version })).to.equal(expectError);
});
}

if (xmlDeclaration !== "") {
for (const { version, expectError } of expectedForcedResults) {
const errorLabel = expectError ? "errors" : "no errors";
it(`and with forced xml version ${version}: ${errorLabel}`, () => {
expect(parse(xmlDeclaration + document, {
defaultXMLVersion: version,
forceXMLVersion: true,
})).to.equal(expectError);
});
}
}
});
}

describe("well-formed for 1.0, not 1.1", () => {
makeTests("without XML declaration", "", WELL_FORMED_1_0_NOT_1_1, [{
version: undefined,
expectError: false,
}, {
version: "1.0",
expectError: false,
}, {
version: "1.1",
expectError: true,
}]);
describe("document well-formed for 1.0, not 1.1", () => {
makeDefaultXMLVersionTests("without XML declaration", "",
WELL_FORMED_1_0_NOT_1_1, [{
version: undefined,
expectError: false,
}, {
version: "1.0",
expectError: false,
}, {
version: "1.1",
expectError: true,
}]);

makeTests("with XML 1.0 declaration", XML_1_0_DECLARATION,
WELL_FORMED_1_0_NOT_1_1, [{
version: undefined,
expectError: false,
}, {
version: "1.0",
expectError: false,
}, {
version: "1.1",
// The XML declaration overrides defaultXMLVersion.
expectError: false,
}]);
makeDefaultXMLVersionTests("with XML 1.0 declaration", XML_1_0_DECLARATION,
WELL_FORMED_1_0_NOT_1_1, [{
version: undefined,
expectError: false,
}, {
version: "1.0",
expectError: false,
}, {
version: "1.1",
// The XML declaration overrides
// defaultXMLVersion.
expectError: false,
}], [{
version: "1.0",
expectError: false,
}, {
version: "1.1",
expectError: true,
}]);

makeTests("with XML 1.1 declaration", XML_1_1_DECLARATION,
WELL_FORMED_1_0_NOT_1_1, [{
version: undefined,
// The XML declaration overrides defaultXMLVersion.
expectError: true,
}, {
version: "1.0",
// The XML declaration overrides defaultXMLVersion.
expectError: true,
}, {
version: "1.1",
expectError: true,
}]);
makeDefaultXMLVersionTests("with XML 1.1 declaration", XML_1_1_DECLARATION,
WELL_FORMED_1_0_NOT_1_1, [{
version: undefined,
// The XML declaration overrides
// defaultXMLVersion.
expectError: true,
}, {
version: "1.0",
// The XML declaration overrides
// defaultXMLVersion.
expectError: true,
}, {
version: "1.1",
expectError: true,
}], [{
version: "1.0",
expectError: false,
}, {
version: "1.1",
expectError: true,
}]);
});

describe("well-formed for 1.1, not 1.0", () => {
makeTests("without XML declaration", "", WELL_FORMED_1_1_NOT_1_0, [{
version: undefined,
expectError: true,
}, {
version: "1.0",
expectError: true,
}, {
version: "1.1",
expectError: false,
}]);
describe("document well-formed for 1.1, not 1.0", () => {
makeDefaultXMLVersionTests("without XML declaration", "",
WELL_FORMED_1_1_NOT_1_0, [{
version: undefined,
expectError: true,
}, {
version: "1.0",
expectError: true,
}, {
version: "1.1",
expectError: false,
}]);

makeTests("with XML 1.0 declaration", XML_1_0_DECLARATION,
WELL_FORMED_1_1_NOT_1_0, [{
version: undefined,
expectError: true,
}, {
version: "1.0",
expectError: true,
}, {
version: "1.1",
// The XML declaration overrides defaultXMLVersion.
expectError: true,
}]);
makeDefaultXMLVersionTests("with XML 1.0 declaration",
XML_1_0_DECLARATION,
WELL_FORMED_1_1_NOT_1_0, [{
version: undefined,
expectError: true,
}, {
version: "1.0",
expectError: true,
}, {
version: "1.1",
// The XML declaration overrides
// defaultXMLVersion.
expectError: true,
}], [{
version: "1.0",
expectError: true,
}, {
version: "1.1",
expectError: false,
}]);

makeTests("with XML 1.1 declaration", XML_1_1_DECLARATION,
WELL_FORMED_1_1_NOT_1_0, [{
version: undefined,
// The XML declaration overrides defaultXMLVersion.
expectError: false,
}, {
version: "1.0",
// The XML declaration overrides defaultXMLVersion.
expectError: false,
}, {
version: "1.1",
expectError: false,
}]);
makeDefaultXMLVersionTests("with XML 1.1 declaration",
XML_1_1_DECLARATION,
WELL_FORMED_1_1_NOT_1_0, [{
version: undefined,
// The XML declaration overrides
// defaultXMLVersion.
expectError: false,
}, {
version: "1.0",
// The XML declaration overrides
// defaultXMLVersion.
expectError: false,
}, {
version: "1.1",
expectError: false,
}], [{
version: "1.0",
expectError: true,
}, {
version: "1.1",
expectError: false,
}]);
});
});

0 comments on commit 1eedbf8

Please sign in to comment.