Any resources for reading and writing XMP metadata via a UXP Photoshop plug in?

I have created several CEP panels and scripts that display and interact with custom XMP metadata. I’ve searched this forum and I have not found an easy way to do this via UXP plug ins.
I used to be able to retrieve this metadata easily and append it in extendscript:

var docRef = app.activeDocument;
var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
var customField = xmp.getProperty(“http://my.custom.namespace/”, “Custom”);
xmp.setProperty(“http://my.custom.namespace/”, “Custom”, “Test”);
docRef.xmpMetadata.rawData = xmp.serialize(XMPConst.SERIALIZE_USE_COMPACT_FORMAT);

Is there an easy way to do this in the UXP API or BatchPlay?

Did you try looking here?

I have looked through those but have not been able to get them to work for my use. I can retrieve the xmp metadata in a batch play command but I don’t know how to change and set different custom fields individually. @DavideBarranca speaks about using xmlbuilder2 but I am not sure how to implement it with in the plug in. The following is slightly adapted from a few of those sources but fails in reference to the xmlbuilder2.

var bp = require(“photoshop”).action.batchPlay
var getDocumentXMP = () => {
return bp([{
_obj: “get”,
_target: {
_ref: [
{ _property: “XMPMetadataAsUTF8” },
{ _ref: “document”, _enum: “ordinal”, _value: “targetEnum” }
}], { synchronousExecution: true })[0].XMPMetadataAsUTF8

var { convert } = require(‘xmlbuilder2’);
const xmpString = getDocumentXMP();
const obj = convert(xmpString, { format: “object” });

var getDocumentMetadata = ({ key, prefix = ‘custom’, namespace = ‘’ }) => {
const xmpString = getDocumentXMP();
const obj = convert(xmpString, { format: “object” });
return obj[“x:xmpmeta”][‘rdf:RDF’][‘rdf:Description’][${prefix}:${key}] || “nothing”;
var myData = getDocumentMetadata();

In order to use xmlbuilder2, you’ll need to have it as part of your plugin’s bundle. This means it either needs to be copied to your plugin bundle and referenced using a relative path (UXP does not do Node-style module resolution), OR it needs to be added using a bundler like Webpack.

If you take a look at the xmlbuilder2 README, it shows how you could include a <script> tag to load it from a CDN. Instead of doing that, load the URL in your browser and then save that file to your plugin folder – say “xmlbuilder2.min.js” and have it in the same folder as your main file.

Then you can do:

const { convert } = require("./xmlbuilder2.min.js"); /* <- note the relative path & file extension! */