I'm assembling a script to automate the production of different versions of a report. The script will first import the XML file, and then run some other functions to tidy up the Indesign project.
When I run this script,
var myMenuAction = app.menuActions.item("Import XML...");
myMenuAction.invoke();
the "Import XML" dialog box opens up and asks me to select the XML file to import, and after I click "Open" the "XML Import Options" box pops up. So far so good. But after I click "OK" the "Import XML" box pops up again.
This isn't a really critical problem, if I select the file I wanted and the options I wanted the first time through, it doesn't seem to make a difference whether I select them again or just hit "cancel", so the script still does what I want it to, it's just doesn't seem very tidy.
So my question is what to I need to do to get only one round of Import XML dialog boxes?
Proclaimed Guru or not, I was actually flummoxed by this as well. But you got it right with your own observation!
... is it possible that because there are two instances of "Import XML..." in the menus (one under File, the other in the dropdown menu in the Structure window) that both are being invoked?
That is indeed correct. xx.item(yy)
retrieves one or more items from a collection. From Marc Autret's blog:
The big secret is that none of the above methods actually returns any element. . . except to understand an 'element' as an object specifier.
What you get is a reference to 'multiple objects', and yes, there are two menu's called "Import XML...". It's kind of hard to persuade InDesign to show that there are two; myMenuAction.length
does not work (it "is" a single element so it has no length), and myMenuAction.constructor.name
shows [Object MenuAction]
-- again, for a single element. However, alert (myMenuAction.name);
finally shows the (un)expected output:
It took a surprising amount of traversing the DOM to find out how to call just one. I opted to located "File" -> "Import XML...", and this is what it takes:
var myMenu = app.menus.item("Main");
var fileMenu = myMenu.menuElements.item("File");
alert (fileMenu.menuItems.everyItem().name);
var myXmlMenu = fileMenu.menuItems.item("Import XML...");
alert (myXmlMenu.name);
myMenuAction = myXmlMenu.associatedMenuAction;
alert (myMenuAction.name);
myMenuAction.invoke();
You can leave out the alerts if you want to use this. Beware that these strings are not in their localizable forms -- this example will only work on InDesign in English, but not when set to use another interface language.
A better way is to avoid calling menus whenever possible. In this case, you probably can safely replace your code with the following:
folder = Folder.myDocuments;
if (File.fs == "Windows")
myFile = folder.openDlg( 'Load XML', "XML files,*.xml;All files:*.*", false);
else
myFile = folder.openDlg( 'Load XML', function(file)
{
return file instanceof Folder ||
(!(file.hidden) && file.name.match(/\.(xml)$/i));
}, false );
}
if (myFile)
xml = app.activeDocument.importXml(myFile);
A few of the advantages are that it's locale independent; you can customize the "Open" dialog to start in another folder (for example, the one where your current document is saved) and use other or more file filters; you can import your XML into the current document, or straight into an existing element (the script version of "Import into Selected Element" in the Import XML dialog); you get a reference to the freshly loaded XML object, so you can immediately post-process it after importing.