We have a list of Framemaker document files (*.fm files) coming into a folder. We need to pick up these files and convert to xml format (same as the saveAs opertion from the File menu).
I have written the follwing function to Save fm files to xml
Code to Save fm files to xml files
function saveAsXml (doc) {
// Get required parameters for the save function.
var params = GetSaveDefaultParams();
var returnParamsp = new PropVals();
// Replace the .fm extension with .mif.
var saveName = doc.Name.replace (/\.[^\.\\]+$/,".xml");
var i = GetPropIndex(params, Constants.FS_FileType);
params[i].propVal.ival = Constants.FV_SaveFmtXml;
// Save the document as XML.
doc.Save(saveName, params, returnParamsp);
}
How to automate this process so that code checks -
Thanks
如果您在Windows上,则可以编写一个简单的批处理文件,以通过命令行中的批处理文件(.bat)在循环中运行您的扩展脚本。
I needed to save a set of FrameMaker .book files as .xml files. To do this, I wrote a perl script that runs under Windows 10 WSL (Windows Subsystem for Linux). It takes two arguments: a .book file filename , and an XML output directory name :
fm2xml.pl /foo/bar/mybook.book ./xmldir/mybook/
This perl script writes out a temporary ExtendScript file into the Adobe Scripts directory in My Documents (to avoid security dialog boxes), then runs it, then prints the console output from the XML save. You'll need the ExtendScript Toolkit installed as well as FrameMaker.
Here's the fm2xml.pl
script:
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
use File::Path qw(make_path remove_tree);
my $book_file = shift;
my $bookname = (basename($book_file));
$bookname =~ s!\.book$!!;
my $xml_dir = (shift or "./${bookname}_xml");
my $xml_dir_temp = $xml_dir.'_TEMP';
my $xml_file_temp = $xml_dir_temp."/${bookname}.xml";
my $maker_ini = <<'EOS';
[Frame]
ProductInterface=Structured FrameMaker
[Preferences]
ThorMessageShown=On
UnavailableFontsDialog=Off
EOS
`echo "$maker_ini" > /mnt/c/Users/$ENV{USER}/AppData/Roaming/Adobe/FrameMaker/14/maker.ini`;
my $jsx_script = <<'EOS';
#target framemaker-14.0
var books = [
"BOOK_FILE",
];
main();
function main() {
var count = books.length;
for (i = 0; i < count; i+= 1) {
Console("Converting " + books[i]);
convertBook(books[i]);
}
// alert("Finished");
// app.Close(Constants.FF_CLOSE_MODIFIED);
}
function convertBook (bookname) {
Console(" Opening book " + bookname);
SimpleOpen(bookname);
var book = app.ActiveBook;
Console(" Opened book " + book.Name);
fixLinks(book);
Console(" Saving as XML...");
var xmlName = saveAsXml (book);
Console(" Closing everything in " + book.Name);
CloseAll();
}
function fixLinks (book) {
var comp = book.FirstComponentInBook;
var docs = [];
while(comp.ObjectValid()) {
Console(" Opening doc " + comp.Name);
var doc = OpenFile(comp.Name);
Console(" Opened doc " + doc.Name);
docs.push(doc);
comp = comp.NextBookComponentInDFSOrder;
}
Console(" Fixing links...");
CallClient("XRefWizard", "SetIDs---" + book.Name + "---DoReporting");
Console(" Fixed links...");
}
function saveAsXml (doc) {
// Get required parameters for the save function.
var params = GetSaveDefaultParams();
var returnParamsp = new PropVals();
// Replace the .fm extension with .xml
var saveName = "XML_FILE";
Console(" Saving to '" + saveName + "'...");
var i = GetPropIndex(params, Constants.FS_FileType);
params[i].propVal.ival = Constants.FV_SaveFmtXml;
// Save the document as XML.
doc.Save(saveName, params, returnParamsp);
}
function OpenFile(path) {
props = new PropVals();
props = GetOpenDefaultParams();
props[GetPropIndex(props, Constants.FS_AlertUserAboutFailure)].propVal.ival = false;
props[GetPropIndex(props, Constants.FS_FileIsInUse)].propVal.ival = Constants.FV_ResetLockAndContinue;
props[GetPropIndex(props, Constants.FS_BookIsInUse)].propVal.ival = Constants.FV_ResetLockAndContinue;
props[GetPropIndex(props, Constants.FS_LockCantBeReset)].propVal.ival = Constants.FV_DoOK;
props[GetPropIndex(props, Constants.FS_FileIsOldVersion)].propVal.ival = Constants.FV_DoOK;
props[GetPropIndex(props, Constants.FS_FontChangedMetric)].propVal.ival = Constants.FV_DoOK;
props[GetPropIndex(props, Constants.FS_FontNotFoundInCatalog)].propVal.ival = Constants.FV_DoOK;
props[GetPropIndex(props, Constants.FS_FontNotFoundInDoc)].propVal.ival = Constants.FV_DoOK;
props[GetPropIndex(props, Constants.FS_LanguageNotAvailable)].propVal.ival = Constants.FV_DoOK;
props[GetPropIndex(props, Constants.FS_UpdateXRefs)].propVal.ival = Constants.FV_DoNo;
props[GetPropIndex(props, Constants.FS_UseRecoverFile)].propVal.ival = Constants.FV_DoNo;
props[GetPropIndex(props, Constants.FS_UseAutoSaveFile)].propVal.ival = Constants.FV_DoNo;
props[GetPropIndex(props, Constants.FS_OpenFileNotWritable)].propVal.ival = Constants.FV_DoOK;
returnp = new PropVals();
var file = Open(path, props, returnp);
return file;
}
function CloseAll()
{
doc=app.FirstOpenDoc
while(doc.id !=0)
{
doc2=doc.NextOpenDocInSession;
Console(" Closing doc " + doc.Name + "...");
doc.Close(Constants.FF_CLOSE_MODIFIED);
doc = doc2;
}
book=app.FirstOpenBook
while(book.id !=0)
{
book2=book.NextOpenBookInSession;
Console(" Closing book " + book.Name + "...");
book.Close(Constants.FF_CLOSE_MODIFIED);
book=book2
}
}
EOS
print "Processing book '$book_file'...\n";
`echo -n '' > /mnt/c/users/$ENV{USER}/AppData/Roaming/Adobe/FrameMaker/14/consfile.txt`; # empty out the log file
my $jsx_file = "/mnt/c/Users/$ENV{USER}/Documents/Adobe Scripts/fm_to_xml.jsx"; # script must be here to avoid Adobe security warnings
remove_tree($xml_dir, $xml_dir_temp);
make_path($xml_dir_temp);
chomp (my $book_file_win = `wslpath -a -w '$book_file'`);
chomp (my $xml_file_win = `wslpath -a -w '$xml_file_temp'`);
chomp (my $jsx_file_win = `wslpath -a -w '$jsx_file'`);
$book_file_win =~ s!\\!\\\\!g;
$xml_file_win =~ s!\\!\\\\!g;
$jsx_script =~ s!BOOK_FILE!$book_file_win!;
$jsx_script =~ s!XML_FILE!$xml_file_win!;
open(JSX_FILE, '>', "${jsx_file}") or die "Can't open '${jsx_file}': $!";
print JSX_FILE $jsx_script;
close JSX_FILE;
my $book_dir = dirname($book_file);
`find '$book_dir' -name '*.lck' -print0 | xargs -0r rm`; # try to remove lingering lock files
my $cmd = "\"/mnt/c/Program\ Files\ \(x86\)/Adobe/Adobe\ ExtendScript\ Toolkit\ CC/ExtendScript\ Toolkit.exe\" -run '$jsx_file_win'";
print "Running:\n $cmd\n";
`$cmd`;
my $start_time = time();
while (!-e "${book_file}.lck" && (time() - $start_time) < 10) {`sleep 2`;}
print "Waiting for book lock file to disappear...\n";
while (-e "${book_file}.lck") {`sleep 2`;}
print `cat /mnt/c/users/chrispy/AppData/Roaming/Adobe/FrameMaker/14/consfile.txt | egrep -v '(is not available|will be used in this session)'`; # strip out missing font messages
if (-e $xml_file_temp) {
`sed -i 's!\\]\\]>!]]\\>!' $xml_dir_temp/*.e*`; # ']]>' must be escaped in XML, but FrameMaker doesn't
print "\n*** XML write for '$bookname' succeeded.\n\n";
rename($xml_dir_temp, $xml_dir);
} else {
print "\n*** XML write for '$bookname' FAILED.\n\n";
remove_tree($xml_dir_temp);
}
Caveat emptor: This whole approach is hacky. The "error-checking" is a ten-second timeout after which it throws up its hands if it sees no signs of life from FrameMaker.
Note that in my case, I use Russ Ward's excellent XRef Wizard plugin to fix duplicate IDs that mess up XML output. If you have this plugin, uncomment the fixLinks(book)
line above.
If you're running a different version than FrameMaker 2017, you'll need to change the #target comment in the embedded JSX script.
If you're a glutton for punishment, you can also try the Makefile I used to automate this:
FM2XML = $(shell which fm2xml.pl)
fm_book_files := \
some/dir/book1.book \
/yet/another/book2.book
book_names := $(patsubst %.book, %, $(notdir $(fm_book_files)))
xml_dirs := $(foreach b, $(book_names), ./xml/$b)
dirs := $(dir ${fm_book_files})
vpath %.book $(dir $(fm_book_files))
all: $(xml_dirs)
print-%: ; @echo $* = $($*)
.SECONDEXPANSION:
$(xml_dirs): ./xml/%: %.book
${FM2XML} ${<} ${@}
But if you hold your breath and don't move, it all works. :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.