Hi,
I’m trying to get, set and delete a namespaced key, value pair on the XMP at the document’s level. I’ve borrowed @simonhenke code from this post on Layer XMP, and edited a bit to transform it on Document XMP. I’m using xmldom
, and I’ve got this:
const bp = require("photoshop").action.batchPlay
const { DOMParser, XMLSerializer, DOMImplementation } = require('xmldom');
// Get all the Doc XMP
const getDocumentXMP = () => {
return bp([{
_obj: "get",
_target: {
_ref: [
{ _property: "XMPMetadataAsUTF8" },
{ _ref: "document", _enum: "ordinal", _value: "targetEnum" }
]
}
}], { synchronousExecution: true })[0].XMPMetadataAsUTF8
}
// Set all the Doc XMP
const setDocumentXMP = (xmpString) => {
bp([{
_obj: "set",
_target: [
{ _ref: "property", _property: "XMPMetadataAsUTF8" },
{ _ref: "document", _enum: "ordinal", _value: "targetEnum" }
],
to: {
_obj: "document",
XMPMetadataAsUTF8: xmpString
}
}], {});
}
// Get key of namespace
export const getDocumentMetadata = ({ key, namespace }) => {
const xmpString = getDocumentXMP();
if (xmpString) {
const xmlDoc = new DOMParser().parseFromString(xmpString, 'text/xml');
const node = namespace ? xmlDoc.getElementsByTagNameNS(namespace, key)[0] : xmlDoc.getElementsByTagName(key)[0]
if (node) {
return node.textContent
}
}
}
// set key, value of namespace
export const setDocumentMetadata = ({ key, value, namespace }) => {
const xmpString = getDocumentXMP();
const xmlDoc = xmpString ? new DOMParser().parseFromString(xmpString, 'text/xml') : new DOMImplementation().createDocument(namespace, key, null);
const node = namespace ? xmlDoc.getElementsByTagNameNS(namespace, key)[0] || xmlDoc.createElementNS(namespace, key) :
xmlDoc.getElementsByTagName(key)[0] || xmlDoc.createElement(key);
node.textContent = value;
xmlDoc.appendChild(node);
console.log(xmlDoc); // the document does contain the new node
const newXmpString = new XMLSerializer().serializeToString(xmlDoc); // <= something wrong here...?
console.log("oldXmpString", xmpString); // Old XMP string
console.log("newXmpString", newXmpString); // New XMP string... they're equal :-/
setDocumentXMP(newXmpString)
}
// delete key of namespace
export const deleteDocumentMetadata = ({ key, namespace }) => {
const xmpString = getDocumentXMP();
const xmlDoc = new DOMParser().parseFromString(xmpString, 'text/xml');
const node = namespace ? xmlDoc.getElementsByTagNameNS(namespace, key)[0] : xmlDoc.getElementsByTagName(key)[0]
if (node) {
xmlDoc.removeChild(node)
setDocumentXMP(new XMLSerializer().serializeToString(xmlDoc))
}
}
// TEST
setDocumentMetadata({key: "someKey", value: "someValue", namespace: "undavide:"})
var newXMP = getDocumentMetadata({key: "myKey", namespace: "undavide:"});
console.log({newXMP}) // undefined
Which in theory should work, in practice it doesn’t. The test sets a namespaced key, value pair, then retrieves it but it gets through as undefined
.
I think I’ve been able to pinpoint the problem in the setDocumentMetadata()
function. The new node
is successfully created and also appended to the xmlDoc
, as the log in the Console shows. For some reason, though, the XMLSerializer()
produces a newXmpString
that is perfectly equal to the original one, that is to say without the new node. I’m logging them both. From that point onwards, the subsequent call to setDocumentXMP()
is pointless, because the new xml string lacks the additional node.
Can your fresh pairs of eyes spot any issue in the above code?
Thanks!!
Davide