Adobe FrameMaker FDK, 構造化されたドキュメントの要素を順にたどって要素の属性を列挙するAPI Client
DocbookXMLで内容を記述し、それを構造化FrameMakerでフォーマットしている。
フォーマット(スタイル)の指定のほとんどはEDDであらかじめ指定しておけばよいのだが、
仕上げの段階の「詰め」の作業などで、どうしてもスポット的に行間を狭めたり、長体をかけたり、という
例外的なフォーマット指定を行う必要が生じる。
これをタッチアップと称して、FrameMaker上で手作業で行うのだが、
この手作業の結果は、次にDocbookXMLから再度フォーマットし直したときに失われてしまう。
(ラウンドトリップして、FrameMakerからDocbookに再度書き戻せられれば問題ないのだが、そうなっていない。
というか、Docbookにはスタイルを記録できる要素や属性は定義されていなから基本的には無理なわけだが...)
したがって、フォーマットのたびに毎回同じ手作業による修正が発生してしまいます。
前置きが長くなりましたが、このタッチアップを少しでも減らすために、 DocbookXMLをFrameMakerで開いたときに各要素に埋め込まれたスタイル指定情報(※)を読み出して そのスタイル適用するAPI ClientをFDKを使って書いてみようと、そういう話です。
※もちろんDocbookXMLにはスタイル情報を記録できる要素や属性はないので、ちょっとしたトリックを使う必要はあります。
まだ道半ば(もいいところなの)ですが、まずは、構造図に表示される要素ツリーを順にたどって、 各要素の属性を取得するところまで作動するものができたので、ここにメモしておきます。
C と C++
FDKは C と C++ のどちらでも書けることになっています。 いままで C のみで書いてきましたが、ちょっとコードが複雑になってきて、C++で書いた方が 楽になってきたので、今回はC++ にも挑戦してみました。
C版 chkelemattr
要素ツリーをたどって要素の属性をすべて列挙します。 結果はFrameMakerのコンソールに出力されます。
Elementに関する処理を、ライブラリとして myelement.h,myelement.c にまとめています。
chkelemattr.c
#include "fapi.h"
#include "futils.h"
#include "fstrings.h"
#include "fstrlist.h"
#include "myelement.h"
#define ChkElemAttr 1
VoidT F_ApiInitialize(IntT initialization) {
F_ObjHandleT menuBarId, menuId;
menuBarId = F_ApiGetNamedObject(FV_SessionId,FO_Menu,"!MakerMainMenu");
menuId = F_ApiDefineAndAddMenu(menuBarId,"APIMenu","myapi");
F_ApiDefineAndAddCommand(ChkElemAttr, menuId,"ChkElemAttr", "chk element attributes", "");
}
BoolT traverseElement( F_ObjHandleT docId, F_ObjHandleT elementId ) {
StringT eleName;
IntT i;
StringListT list;
StringT attrname;
StringT attrvalue;
if( elementId ){
for(
elementId = F_ApiGetId( docId, elementId, FP_FirstChildElement ) ;
elementId ;
elementId = F_ApiGetId( docId, elementId, FP_NextSiblingElement )
){
myelement_init(docId,elementId);
eleName = myelement_getElementName();//docId,elementId);
F_Printf( NULL, (StringT) "element name=%s \r\n", eleName );
list = myelement_getAttributeNameList();// docId,elementId );
for(i=0; i < F_StrListLen(list); i++){
attrname = F_StrListGet(list, i);
attrvalue = myelement_getAttributeValue( attrname );
if( attrvalue!=NULL ){
F_Printf( NULL, (StringT) "element attribute name =%s \r\n", attrname );
F_Printf( NULL, (StringT) "element attribute value=%s \r\n", attrvalue );
}
}
//freeAttributeNameList( list );
//freeElementName( eleName );
myelement_cleanup();
if( ! traverseElement( docId, elementId ) ) return False;
}
return True;
}
else{
return False;
}
}
VoidT traceStructure( F_ObjHandleT docId ) {
F_ObjHandleT flowId;
F_ObjHandleT elementId;
if( ! docId ) return;
flowId = F_ApiGetId( FV_SessionId, docId, FP_MainFlowInDoc );
elementId = F_ApiGetId( docId, flowId, FP_HighestLevelElement );
traverseElement( docId , elementId );
}
VoidT doChkAttribute(){
F_ObjHandleT docId;
docId = F_ApiGetId(0,FV_SessionId,FP_ActiveDoc);
traceStructure( docId );
}
VoidT F_ApiCommand(IntT command) {
switch (command) {
case ChkElemAttr:
doChkAttribute();
break;
}
}
myelement.h
#include "fapi.h"
#include "futils.h"
#include "fstrings.h"
#include "fstrlist.h"
myelement_init(F_ObjHandleT docId, F_ObjHandleT elementId);
myelement_cleanup();
StringT myelement_getElementName();
StringListT myelement_getAttributeNameList();
StringT myelement_getAttributeValue( StringT attrname );
myelement.c
#include "fapi.h"
#include "futils.h"
#include "fstrings.h"
#include "fstrlist.h"
#include "myelement.h"
static StringT eleName;
static StringListT list;
//static StringT attrvalue;
static F_ObjHandleT docId;
static F_ObjHandleT elementId;
myelement_init(F_ObjHandleT mydocId, F_ObjHandleT myelementId){
docId = mydocId;
elementId = myelementId;
}
myelement_cleanup(){
if( eleName!=NULL )
F_Free( eleName );
if( list!=NULL )
F_StrListFree(list);
/*
if( attrvalue!=NULL )
F_Free( attrvalue );
*/
}
StringT myelement_getElementName(){
F_ObjHandleT eltDefId = F_ApiGetId( docId, elementId, FP_ElementDef );
eleName = F_ApiGetString( docId, eltDefId, FP_Name );
return eleName;
}
StringListT myelement_getAttributeNameList(){
IntT i;
F_AttributesT attrs;
F_AttributeT attr;
list = F_StrListNew((UIntT)1,(UIntT)1);
attrs = F_ApiGetAttributes(docId,elementId);
for (i=0; i < attrs.len; i++) {
attr = attrs.val[i];
F_StrListAppend(list,attr.name); // append attribute-name to list
}
return list;
}
StringT myelement_getAttributeValue( StringT attrname ){
UIntT i;
F_AttributesT attrs;
F_AttributeT attr;
F_StringsT strs;
// init
//attrvalue=F_StrCopyString((StringT)"");
attrs = F_ApiGetAttributes(docId,elementId);
for (i=0; i < attrs.len; i++) {
attr = attrs.val[i];
if( F_StrEqual( attrname , attr.name ) ){
strs = attr.values;
if( strs.len>0 ){
//attrvalue = strs.val[0];
return strs.val[0];
}
}
}
return "";
}