Merge pull request #13618 from calixteman/bind_root

XFA - Always bind root subform on root data
This commit is contained in:
Brendan Dahl 2021-06-23 13:14:12 -07:00 committed by GitHub
commit f4f00a9bc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 3 deletions

View File

@ -55,12 +55,12 @@ class Binder {
this.root = root;
this.datasets = root.datasets;
if (root.datasets && root.datasets.data) {
this.emptyMerge = false;
this.data = root.datasets.data;
} else {
this.emptyMerge = true;
this.data = new XmlObject(NamespaceIds.datasets.id, "data");
}
this.emptyMerge = this.data[$getChildren]().length === 0;
this.root.form = this.form = root.template[$clone]();
}
@ -477,6 +477,23 @@ class Binder {
if (this._mergeMode === undefined && child[$nodeName] === "subform") {
this._mergeMode = child.mergeMode === "consumeData";
// XFA specs p. 182:
// The highest-level subform and the data node representing
// the current record are special; they are always
// bound even if their names don't match.
const dataChildren = dataNode[$getChildren]();
if (dataChildren.length > 0) {
this._bindOccurrences(child, [dataChildren[0]], null);
} else if (this.emptyMerge) {
const dataChild = new XmlObject(
dataNode[$namespaceId],
child.name || "root"
);
dataNode[$appendChild](dataChild);
this._bindElement(child, dataChild);
}
continue;
}
let global = false;
@ -570,21 +587,29 @@ class Binder {
}
match = matches.length > 0 ? matches : null;
} else {
// If we've an empty merge, there are no reason
// to make multiple bind so skip consumed nodes.
match = dataNode[$getRealChildrenByNameIt](
child.name,
/* allTransparent = */ false,
/* skipConsumed = */ false
/* skipConsumed = */ this.emptyMerge
).next().value;
if (!match) {
// We're in matchTemplate mode so create a node in data to reflect
// what we've in template.
match = new XmlObject(dataNode[$namespaceId], child.name);
if (this.emptyMerge) {
match[$consumed] = true;
}
dataNode[$appendChild](match);
// Don't bind the value in newly created node because it's empty.
this._bindElement(child, match);
continue;
}
if (this.emptyMerge) {
match[$consumed] = true;
}
match = [match];
}
}

View File

@ -219,4 +219,55 @@ describe("XFAFactory", function () {
expect(field2).not.toEqual(null);
});
});
it("should have an input or textarea", function () {
const xml = `
<?xml version="1.0"?>
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
<template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
<subform name="root" mergeMode="matchTemplate">
<pageSet>
<pageArea>
<contentArea x="123pt" w="456pt" h="789pt"/>
<medium stock="default" short="456pt" long="789pt"/>
<field y="1pt" w="11pt" h="22pt" x="2pt">
<ui>
<textEdit multiLine="1"/>
</ui>
</field>
</pageArea>
</pageSet>
<subform name="first">
<field y="1pt" w="11pt" h="22pt" x="2pt" name="hello">
<ui>
<textEdit/>
</ui>
<value>
<integer/>
</value>
</field>
</subform>
</subform>
</template>
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
<xfa:data>
<toto>
<first>
<hello>123
</hello>
</first>
</toto>
</xfa:data>
</xfa:datasets>
</xdp:xdp>
`;
const factory = new XFAFactory({ "xdp:xdp": xml });
expect(factory.numberPages).toEqual(1);
const pages = factory.getPages();
const field1 = searchHtmlNode(pages, "name", "input");
expect(field1).not.toEqual(null);
expect(field1.attributes.value).toEqual("123");
});
});