XFA - Created data node mustn't belong to datasets namespace
- when some named nodes in the template don't have their counterpart in datasets we create some nodes: the main node mustn't belong to the datasets namespace because it doesn't make sense and Acrobat Reader isn't able to read pdf with such nodes. - so created nodes under a datasets node have a namespaceId set to -1 and consequently when serialized no namespace prefix will appear.
This commit is contained in:
parent
804abb3786
commit
57ae3a5a76
@ -45,6 +45,8 @@ import { createDataNode, searchNode } from "./som.js";
|
||||
import { NamespaceIds } from "./namespaces.js";
|
||||
import { warn } from "../../shared/util.js";
|
||||
|
||||
const NS_DATASETS = NamespaceIds.datasets.id;
|
||||
|
||||
function createText(content) {
|
||||
const node = new Text({});
|
||||
node[$content] = content;
|
||||
@ -501,8 +503,12 @@ class Binder {
|
||||
if (dataChildren.length > 0) {
|
||||
this._bindOccurrences(child, [dataChildren[0]], null);
|
||||
} else if (this.emptyMerge) {
|
||||
const nsId =
|
||||
dataNode[$namespaceId] === NS_DATASETS
|
||||
? -1
|
||||
: dataNode[$namespaceId];
|
||||
const dataChild = (child[$data] = new XmlObject(
|
||||
dataNode[$namespaceId],
|
||||
nsId,
|
||||
child.name || "root"
|
||||
));
|
||||
dataNode[$appendChild](dataChild);
|
||||
@ -625,10 +631,11 @@ class Binder {
|
||||
if (!match) {
|
||||
// We're in matchTemplate mode so create a node in data to reflect
|
||||
// what we've in template.
|
||||
match = child[$data] = new XmlObject(
|
||||
dataNode[$namespaceId],
|
||||
child.name
|
||||
);
|
||||
const nsId =
|
||||
dataNode[$namespaceId] === NS_DATASETS
|
||||
? -1
|
||||
: dataNode[$namespaceId];
|
||||
match = child[$data] = new XmlObject(nsId, child.name);
|
||||
if (this.emptyMerge) {
|
||||
match[$consumed] = true;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import {
|
||||
XFAObjectArray,
|
||||
XmlObject,
|
||||
} from "./xfa_object.js";
|
||||
import { NamespaceIds } from "./namespaces.js";
|
||||
import { warn } from "../../shared/util.js";
|
||||
|
||||
const namePattern = /^[^.[]+/;
|
||||
@ -51,6 +52,7 @@ const shortcuts = new Map([
|
||||
]);
|
||||
|
||||
const somCache = new WeakMap();
|
||||
const NS_DATASETS = NamespaceIds.datasets.id;
|
||||
|
||||
function parseIndex(index) {
|
||||
index = index.trim();
|
||||
@ -261,7 +263,8 @@ function createNodes(root, path) {
|
||||
let node = null;
|
||||
for (const { name, index } of path) {
|
||||
for (let i = 0, ii = !isFinite(index) ? 0 : index; i <= ii; i++) {
|
||||
node = new XmlObject(root[$namespaceId], name);
|
||||
const nsId = root[$namespaceId] === NS_DATASETS ? -1 : root[$namespaceId];
|
||||
node = new XmlObject(nsId, name);
|
||||
root[$appendChild](node);
|
||||
}
|
||||
|
||||
|
@ -976,8 +976,11 @@ class XmlObject extends XFAObject {
|
||||
this[$content] = value.toString();
|
||||
}
|
||||
|
||||
[$dump]() {
|
||||
[$dump](hasNS = false) {
|
||||
const dumped = Object.create(null);
|
||||
if (hasNS) {
|
||||
dumped.$ns = this[$namespaceId];
|
||||
}
|
||||
if (this[$content]) {
|
||||
dumped.$content = this[$content];
|
||||
}
|
||||
@ -985,7 +988,7 @@ class XmlObject extends XFAObject {
|
||||
|
||||
dumped.children = [];
|
||||
for (const child of this[_children]) {
|
||||
dumped.children.push(child[$dump]());
|
||||
dumped.children.push(child[$dump](hasNS));
|
||||
}
|
||||
|
||||
dumped.attributes = Object.create(null);
|
||||
|
@ -841,6 +841,67 @@ describe("XFAParser", function () {
|
||||
expect(searchNode(data, data, "A")[0][$dump]()).toEqual(expected);
|
||||
});
|
||||
|
||||
it("should make a basic binding and create a non-existing node with namespaceId equal to -1", 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="A">
|
||||
<subform name="B">
|
||||
<field name="C">
|
||||
</field>
|
||||
<field name="D">
|
||||
<value>
|
||||
<text>foobar</text>
|
||||
</value>
|
||||
</field>
|
||||
</subform>
|
||||
</subform>
|
||||
</template>
|
||||
</xdp:xdp>
|
||||
`;
|
||||
const root = new XFAParser().parse(xml);
|
||||
const binder = new Binder(root);
|
||||
const form = binder.bind();
|
||||
const data = binder.getData();
|
||||
|
||||
expect(
|
||||
searchNode(form, form, "A.B.D.value.text")[0][$dump]().$content
|
||||
).toBe("foobar");
|
||||
|
||||
// Created nodes mustn't belong to xfa:datasets namespace.
|
||||
const expected = {
|
||||
$name: "A",
|
||||
$ns: -1,
|
||||
attributes: {},
|
||||
children: [
|
||||
{
|
||||
$name: "B",
|
||||
$ns: -1,
|
||||
attributes: {},
|
||||
children: [
|
||||
{
|
||||
$name: "C",
|
||||
$ns: -1,
|
||||
attributes: {},
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
$name: "D",
|
||||
$ns: -1,
|
||||
attributes: {},
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(searchNode(data, data, "A")[0][$dump](/* hasNS */ true)).toEqual(
|
||||
expected
|
||||
);
|
||||
});
|
||||
|
||||
it("should make another basic binding", function () {
|
||||
const xml = `
|
||||
<?xml version="1.0"?>
|
||||
|
Loading…
x
Reference in New Issue
Block a user