XFA - Remove namespace from nodes under xfa:data node

- in real life some xfa contains xml like <xfa:data><xfa:Foo><xfa:Bar>...</xfa:data>
    since there are no Foo or Bar in the xfa namespace the JS representation are empty
    and that leads to errors.
  - so the idea is to make all nodes under xfa:data namespace agnostic which means
    that ns are removed from nodes in the parser but only xfa:data descendants.
This commit is contained in:
Calixte Denizet 2021-07-21 16:24:53 +02:00
parent 6c9b6bc599
commit 5555114bb3
6 changed files with 43 additions and 5 deletions

View File

@ -18,6 +18,7 @@ import {
$cleanup, $cleanup,
$finalize, $finalize,
$ids, $ids,
$isNsAgnostic,
$nsAttributes, $nsAttributes,
$onChild, $onChild,
$resolvePrototypes, $resolvePrototypes,
@ -67,6 +68,7 @@ class Empty extends XFAObject {
class Builder { class Builder {
constructor() { constructor() {
this._namespaceStack = []; this._namespaceStack = [];
this._nsAgnosticLevel = 0;
// Each prefix has its own stack // Each prefix has its own stack
this._namespacePrefixes = new Map(); this._namespacePrefixes = new Map();
@ -118,18 +120,27 @@ class Builder {
(namespaceToUse && namespaceToUse[$buildXFAObject](name, attributes)) || (namespaceToUse && namespaceToUse[$buildXFAObject](name, attributes)) ||
new Empty(); new Empty();
if (node[$isNsAgnostic]()) {
this._nsAgnosticLevel++;
}
// In case the node has some namespace things, // In case the node has some namespace things,
// we must pop the different stacks. // we must pop the different stacks.
if (hasNamespaceDef || prefixes) { if (hasNamespaceDef || prefixes || node[$isNsAgnostic]()) {
node[$cleanup] = { node[$cleanup] = {
hasNamespace: hasNamespaceDef, hasNamespace: hasNamespaceDef,
prefixes, prefixes,
nsAgnostic: node[$isNsAgnostic](),
}; };
} }
return node; return node;
} }
isNsAgnostic() {
return this._nsAgnosticLevel > 0;
}
_searchNamespace(nsName) { _searchNamespace(nsName) {
let ns = this._namespaces.get(nsName); let ns = this._namespaces.get(nsName);
if (ns) { if (ns) {
@ -178,7 +189,7 @@ class Builder {
} }
clean(data) { clean(data) {
const { hasNamespace, prefixes } = data; const { hasNamespace, prefixes, nsAgnostic } = data;
if (hasNamespace) { if (hasNamespace) {
this._currentNamespace = this._namespaceStack.pop(); this._currentNamespace = this._namespaceStack.pop();
} }
@ -187,6 +198,9 @@ class Builder {
this._namespacePrefixes.get(prefix).pop(); this._namespacePrefixes.get(prefix).pop();
}); });
} }
if (nsAgnostic) {
this._nsAgnosticLevel--;
}
} }
} }

View File

@ -15,6 +15,7 @@
import { import {
$appendChild, $appendChild,
$isNsAgnostic,
$namespaceId, $namespaceId,
$nodeName, $nodeName,
$onChild, $onChild,
@ -29,6 +30,10 @@ class Data extends XmlObject {
constructor(attributes) { constructor(attributes) {
super(DATASETS_NS_ID, "data", attributes); super(DATASETS_NS_ID, "data", attributes);
} }
[$isNsAgnostic]() {
return true;
}
} }
class Datasets extends XFAObject { class Datasets extends XFAObject {

View File

@ -118,12 +118,12 @@ class XFAParser extends XMLParserBase {
return [namespace, prefixes, attributeObj]; return [namespace, prefixes, attributeObj];
} }
_getNameAndPrefix(name) { _getNameAndPrefix(name, nsAgnostic) {
const i = name.indexOf(":"); const i = name.indexOf(":");
if (i === -1) { if (i === -1) {
return [name, null]; return [name, null];
} }
return [name.substring(i + 1), name.substring(0, i)]; return [name.substring(i + 1), nsAgnostic ? "" : name.substring(0, i)];
} }
onBeginElement(tagName, attributes, isEmpty) { onBeginElement(tagName, attributes, isEmpty) {
@ -131,7 +131,10 @@ class XFAParser extends XMLParserBase {
attributes, attributes,
tagName tagName
); );
const [name, nsPrefix] = this._getNameAndPrefix(tagName); const [name, nsPrefix] = this._getNameAndPrefix(
tagName,
this._builder.isNsAgnostic()
);
const node = this._builder.build({ const node = this._builder.build({
nsPrefix, nsPrefix,
name, name,

View File

@ -60,6 +60,7 @@ const $isCDATAXml = Symbol();
const $isBindable = Symbol(); const $isBindable = Symbol();
const $isDataValue = Symbol(); const $isDataValue = Symbol();
const $isDescendent = Symbol(); const $isDescendent = Symbol();
const $isNsAgnostic = Symbol();
const $isSplittable = Symbol(); const $isSplittable = Symbol();
const $isThereMoreWidth = Symbol(); const $isThereMoreWidth = Symbol();
const $isTransparent = Symbol(); const $isTransparent = Symbol();
@ -160,6 +161,10 @@ class XFAObject {
); );
} }
[$isNsAgnostic]() {
return false;
}
[$acceptWhitespace]() { [$acceptWhitespace]() {
return false; return false;
} }
@ -1087,6 +1092,7 @@ export {
$isCDATAXml, $isCDATAXml,
$isDataValue, $isDataValue,
$isDescendent, $isDescendent,
$isNsAgnostic,
$isSplittable, $isSplittable,
$isThereMoreWidth, $isThereMoreWidth,
$isTransparent, $isTransparent,

View File

@ -0,0 +1 @@
https://bugzilla.mozilla.org/attachment.cgi?id=9232367

View File

@ -952,6 +952,15 @@
"enableXfa": true, "enableXfa": true,
"type": "eq" "type": "eq"
}, },
{ "id": "xfa_bug1721600",
"file": "pdfs/xfa_bug1721600.pdf",
"md5": "5f514f476169eeb7254da380a8db495a",
"link": true,
"rounds": 1,
"lastPage": 1,
"enableXfa": true,
"type": "eq"
},
{ "id": "xfa_bug1720182", { "id": "xfa_bug1720182",
"file": "pdfs/xfa_bug1720182.pdf", "file": "pdfs/xfa_bug1720182.pdf",
"md5": "1351f816f0509fe750ca61ef2bd40872", "md5": "1351f816f0509fe750ca61ef2bd40872",