Monday, July 12, 2010 / InDesign, DTP

ExtendScript 自前の相互参照の作成その3 ... 相互参照を更新する/元に戻す

自前の相互参照の作成その1自前の相互参照の作成その2 で相互参照の準備ができているので、いよいよ相互参照を更新します。

相互参照を更新 updateXref.jsx

xref_test.indd をアクティブドキュメントにした状態で実行。

  • 注意1) 相互参照ソースファイルは /Users/foo/xref_src.indd に決めうち(必要ならソースを書きかえて対応)
  • 注意2) タグ付きテキストを使用して更新するため、タグ付きテキストの制約(たとえば画像が扱えないなど)を受ける点に注意。
//
// 相互参照を更新する.
// InDesign CS5
//

var HOME_DIR="/Users/foo";
var TAGGED_TEXT_FILE = new File(HOME_DIR+"/_tmp.txt");

function exportTaggedText( outputfile ,xref_id ){
    function getTf( doc, xref_id ){
        var r = null;

        for( var i=0; i<doc.textFrames.length; i++ ){
            var tf = doc.textFrames.item(i);
            if( tf.label ){
                if( xref_id == tf.label ){
                    r = tf;
                }
            }
        }

        return r;
    }

    function open(){
        var file = File(HOME_DIR+"/xref_src.indd");
        app.open( file );
        return app.activeDocument;
    }
    function close(doc){
        doc.close(SaveOptions.NO);
    }

    var doc = open();
    var tf = getTf( doc, xref_id );
    if( tf && tf.paragraphs.length>0){
        var myStory = tf.parentStory;
        myStory.exportFile(ExportFormat.taggedText,outputfile,false);
    }
    close(doc);
}

function getXrefList( doc ){
    function parse( ele, list ){
        if( ele.markupTag.name == "xref" ){
            list.push( ele );
        }
        for( var i=0; i<ele.xmlElements.length; i++ ){
            var ele2 = ele.xmlElements.item(i);
            parse( ele2,list );
        }
    }

    var list = new Array();

    // ルート要素を取得
    var eRoot = doc.xmlElements.itemByName("Root");
    parse( eRoot,list );

    return list;
}

function updateXref( doc, eXref ){
    var end = eXref.characters.length-1;
    eXref.characters.itemByRange(0,end).place( TAGGED_TEXT_FILE,false);

    // 不要な改行を削除
    var start = eXref.characters.length-1;
    var end = eXref.characters.length-1;
    eXref.characters.itemByRange(start,end).remove();
}

function getId( eXref ){
    var attrs=eXref.xmlAttributes;
    if( attrs.itemByName("id") ){
        var xref_id = attrs.itemByName("id").value;
        return xref_id;
    }
    return null;
}


var doc = app.activeDocument;
var xrefList = getXrefList( doc );
for( var i=0; i<xrefList.length; i++){
    var eXref = xrefList[i];
    var xref_id = getId( eXref );
    if( xref_id ){
        exportTaggedText( TAGGED_TEXT_FILE,xref_id );

        // 該当位置に相互参照ソースを配置
        updateXref( doc, eXref );
    }
}

相互参照を元に戻す revertXref.jsx

更新したら逆にもとの状態に戻したいことがあります。そのときに使用する ExtendScript 。

//
// 相互参照を元に戻す.
// InDesign CS5
//

function getXrefList( doc ){
    function parse( ele, list ){
        if( ele.markupTag.name == "xref" ){
            list.push( ele );
        }
        for( var i=0; i<ele.xmlElements.length; i++ ){
            var ele2 = ele.xmlElements.item(i);
            parse( ele2,list );
        }
    }

    var list = new Array();

    // ルート要素を取得
    var eRoot = doc.xmlElements.itemByName("Root");
    parse( eRoot,list );
    return list;
}

function revertXref( doc,eXref ){
    var xref_id = getId( eXref );
    if( xref_id ){
        var end = eXref.characters.length-1;
        eXref.characters.itemByRange(0,end).contents = "{xref:"+xref_id+"}" ;
    }
}

function stripTag( doc ){
    function removeAttrs(eRoot){
        var attrs=eRoot.xmlAttributes;
        for( var i=0; i<attrs.count(); i++){
            attrs[i].remove();
        }
    }

    var eRoot = doc.xmlElements.itemByName("Root");
    while( eRoot.xmlAttributes.count() >0 ){
        removeAttrs(eRoot);
    }
    while(eRoot.xmlElements.length>0){
        var eles=eRoot.xmlElements;
        for( var j=0; j<eles.length; j++){
            eles[j].untag();
        }
        //doUntag( eles );
    }
}

function getId( eXref ){
    var attrs=eXref.xmlAttributes;
    if( attrs.itemByName("id") ){
        var xref_id = attrs.itemByName("id").value;
        return xref_id;
    }
    return null;
}


var doc = app.activeDocument;
var xrefList = getXrefList( doc );
for( var i=0; i<xrefList.length; i++){
    var eXref = xrefList[i];

    // 元の相互参照記述に戻す
    revertXref( doc, eXref );
}

// XML構造の初期化
stripTag(doc);