The KM message is saying that the xml is a valid plist, but not valid KM export structure.
Your plist is an array of Macros.
It needs to be embedded in a macro group under a Macros key. That macro group needs to. be wrapped in an array.
That will tell KM the macro's destination.
In my testing, this is the minimal macro export structure.
<?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>Macros</key>
<array>
<dict>
<key>Actions</key>
<array/>
<key>Name</key>
<string>Minimal Macro</string>
<key>Triggers</key>
<array/>
</dict>
</array>
<key>Name</key>
<string>Test Group</string>
</dict>
</array>
</plist>
(0-based numbering)
plist (version="1.0")
└─ array (root array)
└─ [0] dict "Macro Group"
├─ key "Macros" → array
│ └─ [0] dict "Macro"
│ ├─ key "Actions" → array (empty)
│ ├─ key "Name" → string "Minimal Macro"
│ └─ key "Triggers" → array (empty)
└─ key "Name" → string "Test Group"
Import it like this:
AppleScript
--How to create/import macros into Keyboard Maestro from code? - Questions & Suggestions - Keyboard Maestro Discourse
-- https://forum.keyboardmaestro.com/t/how-to-create-import-macros-into-keyboard-maestro-from-code/50798/2
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set minimalExportXML to ¬
"<?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>Macros</key>
<array>
<dict>
<key>Actions</key>
<array/>
<key>Name</key>
<string>Minimal Macro</string>
<key>Triggers</key>
<array/>
</dict>
</array>
<key>Name</key>
<string>Test Group</string>
</dict>
</array>
</plist>"
tell application id "com.stairways.keyboardmaestro.editor"
importMacros minimalExportXML
end tell
Another the example is here:
This AppleScript will properly wrap and import your xml.
AppleScript
--How to create/import macros into Keyboard Maestro from code? - Questions & Suggestions - Keyboard Maestro Discourse
-- https://forum.keyboardmaestro.com/t/how-to-create-import-macros-into-keyboard-maestro-from-code/50798/2
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set arrayOfMacroDicts to "<?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>Activate</key>
<string>Normal</string>
<key>Name</key>
<string>zed: LMCache</string>
<key>Triggers</key>
<array/>
<key>UID</key>
<string>2BE3EA71-D7DC-4EE5-9EB8-C8B7875E6CB2</string>
<key>Actions</key>
<array>
<dict>
<key>MacroActionType</key>
<string>IfThenElse</string>
<key>TimeOutAbortsMacro</key>
<true/>
<key>Conditions</key>
<dict>
<key>ConditionList</key>
<array>
<dict>
<key>ConditionType</key>
<string>AnyWindow</string>
<key>AnyWindowConditionType</key>
<string>EndsWith</string>
<key>AnyWindowTitle</key>
<string>LMCache</string>
<key>IsFrontApplication</key>
<false/>
<key>Application</key>
<dict>
<key>BundleIdentifier</key>
<string>dev.zed.Zed</string>
<key>Name</key>
<string>Zed</string>
<key>NewFile</key>
<string>/Applications/Zed.app</string>
</dict>
</dict>
</array>
<key>ConditionListMatch</key>
<string>All</string>
</dict>
<key>ThenActions</key>
<array>
<dict>
<key>MacroActionType</key>
<string>ManipulateWindow</string>
<key>Action</key>
<string>SelectWindow</string>
<key>Targeting</key>
<string>WindowNameContaining</string>
<key>TargetingType</key>
<string>Specific</string>
<key>WindowName</key>
<string>LMCache</string>
<key>TargetApplication</key>
<dict>
<key>BundleIdentifier</key>
<string>dev.zed.Zed</string>
<key>Name</key>
<string>Zed</string>
<key>NewFile</key>
<string>/Applications/Zed.app</string>
</dict>
</dict>
</array>
<key>ElseActions</key>
<array>
<dict>
<key>MacroActionType</key>
<string>ExecuteShellScript</string>
<key>DisplayKind</key>
<string>Window</string>
<key>HonourFailureSettings</key>
<true/>
<key>IncludeStdErr</key>
<false/>
<key>Path</key>
<string></string>
<key>Source</key>
<string>Nothing</string>
<key>Text</key>
<string>open -a /Applications/Zed.app ~/fork-i/LMCache/LMCache</string>
<key>TimeOutAbortsMacro</key>
<true/>
<key>TrimResults</key>
<true/>
<key>TrimResultsNew</key>
<true/>
<key>UseText</key>
<true/>
</dict>
</array>
</dict>
</array>
</dict>
</array>
</plist>"
--Deserialize the array of macros
set macroDicts to (current application's NSString's stringWithString:arrayOfMacroDicts)'s propertyList()
--embed the array of macros into the Macros key of a Macro Group dict
set groupDict to {Macros:macroDicts, |Name|:"tests"}
--wrap the Macro Group dict in an Array
set groupsArray to {groupDict}
--convert back to xml
set exportXML to serializePlistObject(groupsArray)
tell application id "com.stairways.keyboardmaestro.editor"
importMacros exportXML
end tell
on serializePlistObject(plistObject)
set {theData, theError} to current application's NSPropertyListSerialization's dataWithPropertyList:plistObject format:(current application's NSPropertyListXMLFormat_v1_0) options:0 |error|:(reference) -- don't use binary format
if theData is missing value then error (theError's localizedDescription() as text) number -10000
set plist to (current application's NSString's alloc()'s initWithData:theData encoding:(current application's NSUTF8StringEncoding)) as text
end serializePlistObject
(If memory serves, when KM exports macros, it wraps each macro in a macro group individually, but in practice you can put an array of Macros that share the same destination into one Macro Group.