If I copy a macro as XML → edit that XML → how do I reconvert the XML to a new macro?

Hello, if I copy a macro as XML → edit that XML → how do I reconvert the XML to a new macro, ie create a new macro based on that XML?
thanks in advance for your time and help

1 Like

I would personally execute the km plist XML directly, by creating a macro with an Execute AppleScript, or Execute JavaScript for Automation action that

  • calls the do script method of the Keyboard Maestro Engine application,
  • passing the plist XML string to it.

for example:

Make a noise from updated XML Macro (v10.1.1)

Make a noise from updated XML.kmmacros (2.6 KB)


Expand disclosure triangle to view JS Source
(() => {
    "use strict";

    const
        kme = Application("Keyboard Maestro Engine"),
        soundName = "Submarine";

    const xml = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>ActionUID</key>
        <integer>9487349</integer>
        <key>DeviceID</key>
        <string>DEFAULT</string>
        <key>MacroActionType</key>
        <string>PlaySound</string>
        <key>Path</key>
        <string>/System/Library/Sounds/${soundName}.aiff</string>
        <key>TimeOutAbortsMacro</key>
        <true/>
    </dict>
</array>
</plist>`;

    return (
        kme.doScript(xml),
        `Played: ${soundName}.aiff`
    );
})();
1 Like

extremely useful and well written reply and taking the time to write the example using a sound. Thanks very much !

If you have the patience, I have 2 follow-up questions

  • when I save a macro as XML and look at the resulting XML file, there is no trace of the comments in the original macro. Why would this be ? This suggests that the XML could not be reconverted to the original macro.

  • i pasted below a snippet of the XML file. which corresponds to the display text "Change Meeting Date" action shown below.
    The million dollar question and the impetus for my original question:
    Would there be any way to create a macro which would:

  • ask the user to input a variable such as input_reminder_1 (easy to do)

  • create a new ready to use XML (or even better an execute text script action containing the new XML), in which the variable input_reminder_1 in the script is replaced by the user input of that variable.

thanks again very much

		<dict>
			<key>Action</key>
			<string>DisplayBriefly</string>
			<key>ActionUID</key>
			<integer>9161086</integer>
			<key>MacroActionType</key>
			<string>InsertText</string>
			<key>Text</key>
			<string>Change Meeting Date</string>
		</dict>

——————————————————————————

——————————————————————————
note in the XML below that Change Meeting Date is replaced with the user input variable input_reminder_1.


<dict>
			<key>Action</key>
			<string>DisplayBriefly</string>
			<key>ActionUID</key>
			<integer>9161086</integer>
			<key>MacroActionType</key>
			<string>InsertText</string>
			<key>Text</key>
			<string>input_reminder_1</string>
		</dict>

no trace of the comments

Two thoughts:

  1. Make sure that you are selecting and copying a macro, rather than just one or more actions. (It's possible that you didn't copy the comment actions)
  2. If you have copied one or more comment blocks, remember that the comment field is a rich text field, so you may be looking at something which is not human-legible (Base64 encoded RTF), where you expected to see the plain text of your comment.

e.g. for a comment action like this:

you might be looking at XML like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>ActionUID</key>
        <integer>9487876</integer>
        <key>MacroActionType</key>
        <string>Comment</string>
        <key>StyledText</key>
        <data>
        cnRmZAAAAAADAAAAAgAAAAcAAABUWFQucnRmAQAAAC7bAQAAKwAAAAEAAADT
        AQAAe1xydGYxXGFuc2lcYW5zaWNwZzEyNTJcY29jb2FydGYyNTgwClxjb2Nv
        YXRleHRzY2FsaW5nMFxjb2NvYXBsYXRmb3JtMHtcZm9udHRibFxmMFxmc3dp
        c3NcZmNoYXJzZXQwIEhlbHZldGljYTtcZjFcZnN3aXNzXGZjaGFyc2V0MCBI
        ZWx2ZXRpY2EtQm9sZDt9CntcY29sb3J0Ymw7XHJlZDI1NVxncmVlbjI1NVxi
        bHVlMjU1O1xyZWQwXGdyZWVuMFxibHVlMDt9CntcKlxleHBhbmRlZGNvbG9y
        dGJsOztcY3NzcmdiXGMwXGMwXGMwXGM4NDcwNlxjbmFtZSBjb250cm9sVGV4
        dENvbG9yO30KXHBhcmRcdHg1NjBcdHgxMTIwXHR4MTY4MFx0eDIyNDBcdHgy
        ODAwXHR4MzM2MFx0eDM5MjBcdHg0NDgwXHR4NTA0MFx0eDU2MDBcdHg2MTYw
        XHR4NjcyMFxwYXJkaXJuYXR1cmFsXHBhcnRpZ2h0ZW5mYWN0b3IwCgpcZjBc
        ZnMzMFxmc21pbGxpMTUzNjQgXGNmMiBTb21lIApcZjFcYiByaWNoIHRleHQK
        XGYwXGIwICBkZXRhaWwgaGVyZX0BAAAAIwAAAAEAAAAHAAAAVFhULnJ0ZhAA
        AADxRKNitgEAAAAAAAAAAAAA
        </data>
        <key>Title</key>
        <string>Some kind of comment title</string>
    </dict>
</array>
</plist>


the variable input_reminder_1 in the script is replaced by the user input of that variable.

In the Execute JavaScript for Automation action in which you call .doScript(xml) you can obtain a value for a given KM variable name with an incantation like:

const newValue = Application("Keyboard Maestro Engine").getvariable(
    "input_reminder_1"
)

and if you look at the detail of the sound-playing example above, you will see that you can interpolate a named value into the XML between ${ ... } (JavaScript Template literals (Template strings))

e.g.

<string>/System/Library/Sounds/${soundName}.aiff</string>
1 Like

fantastic ! thanks very much !