我们将 Framemaker 文档文件(*.fm 文件)列表放入文件夹中。我们需要选取这些文件并转换为 xml 格式(与“文件”菜单中的“另存为”操作相同)。
我已经编写了以下函数来将 fm 文件保存到 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);
}
如何自动化此过程以便进行代码检查 -
谢谢
如果您使用的是 Windows,您可以编写一个简单的批处理文件,通过命令行中的批处理文件 (.bat) 循环运行扩展脚本。
我需要将一组 FrameMaker .book 文件另存为 .xml 文件。为此,我编写了一个在 Windows 10 WSL(适用于 Linux 的 Windows 子系统)下运行的 perl 脚本。它需要两个参数:一个 .book 文件 文件名,和一个 XML 输出 目录名称:
fm2xml.pl /foo/bar/mybook.book ./xmldir/mybook/
此 perl 脚本将临时 ExtendScript 文件写入“我的文档”中的 Adobe Scripts 目录(以避免出现安全对话框),然后运行它,然后打印 XML 保存的控制台输出。您需要安装 ExtendScript Toolkit 以及 FrameMaker。
这是
fm2xml.pl
脚本:
#!/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);
}
买者自负:整个方法都很hacky。 “错误检查”是十秒的超时,之后如果没有看到 FrameMaker 的任何生命迹象,它就会举手。
请注意,在我的例子中,我使用 Russ Ward 出色的 XRef Wizard 插件 来修复导致 XML 输出混乱的重复 ID。如果您有此插件,请取消注释上面的
fixLinks(book)
行。
如果您运行的版本与 FrameMaker 2017 不同,则需要更改嵌入式 JSX 脚本中的 #target 注释。
如果你是一个贪图惩罚的人,你也可以尝试我用来自动化这个的Makefile:
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} ${<} ${@}
但是如果你屏住呼吸不动,一切都会起作用。 :)
您可以使用 Frame Developer’s Kit™ (FDK) 来完成此操作。