Skip to main content
FabianK007
Known Participant
May 29, 2018
Answered

Verify References in a Ditamap - ExtendScript

  • May 29, 2018
  • 1 reply
  • 707 views

Hi Folks,

I wrote a script to verify if all the files referenced in a ditamap exist. The script is rather slow when the a ditamap refers to other ditamaps because the script opens those ditamaps.

var doc = app.FirstOpenDoc;

CheckDITATopicref(doc)

function CheckDITATopicref(doc) {

    var DITATopicref = doc.FirstDITATopicrefElementInDoc;

    while(DITATopicref.ObjectValid()) {

        var myFile = new File(DITATopicref.TopicRefAbsoluteFilePath);

        if (!(myFile.exists)) {

            $.writeln("The following file is missing: "+ DITATopicref.TopicRefAbsoluteFilePath)

        } else {

            if(DITATopicref.TopicRefAbsoluteFilePath.split(".")[DITATopicref.TopicRefAbsoluteFilePath.split(".").length-1] == "ditamap"){ //if file is ditamap

                var Topicref = Open(DITATopicref.TopicRefAbsoluteFilePath, GetOpenDefaultParams (), new PropVals());

                CheckDITATopicref (Topicref)

                Topicref.Close(Constants.FF_CLOSE_MODIFIED);

            }

        }

        DITATopicref = DITATopicref.NextDITATopicrefElementInDoc;

    }

}

I'm wondering if there are faster methods.

  1. Is opening the ditamap mandatory to do the verification?
  2. Do I need to loop through the topicrefs to find the missing ones?

Regards

This topic has been closed for replies.
Correct answer 4everJang

Hello Fabian,

The answer is: yes, you need to open each dita map in order to check what topicrefs are inside. But no, you should not open them in FM as that adds a lot of processing steps that make it really slow. ExtendScript features XML support, as described in the JavaScript Tools Guide​. Check the chapter on using the XML object in that guide.

function ReadXML( filename )

{

    var xmlMap;

    var oFile = File( filename );

    if( oFile.open( 'r' ) )

    {

         sContents = oFile.read( oFile.length );

         oFile.close( );

         xmlMap = new XML( sContents );

    }

    return xmlMap;

}

Processing the xml object is total luxury compared to anything else:

var xmlTopicRefs = xmlMap..topicref;       // the double colon enables retrieval of any <topicref> descendant.

for( i = 0; i < xmlTopicRefs.length( ); i++ )

{

     var sHref = xmlTopicRefs.@href.toString( );

     ... prepend the map's base path and check if the sHref points to an existing file ...

}

Note that the length property on an XML object does not exist - it is implemented as a length( ) function instead.

Also note that I have skipped the usual extensive error handling in the above code. You will be able to figure that out, no doubt.

Kind regards

Jang

1 reply

4everJang
4everJangCorrect answer
Legend
May 29, 2018

Hello Fabian,

The answer is: yes, you need to open each dita map in order to check what topicrefs are inside. But no, you should not open them in FM as that adds a lot of processing steps that make it really slow. ExtendScript features XML support, as described in the JavaScript Tools Guide​. Check the chapter on using the XML object in that guide.

function ReadXML( filename )

{

    var xmlMap;

    var oFile = File( filename );

    if( oFile.open( 'r' ) )

    {

         sContents = oFile.read( oFile.length );

         oFile.close( );

         xmlMap = new XML( sContents );

    }

    return xmlMap;

}

Processing the xml object is total luxury compared to anything else:

var xmlTopicRefs = xmlMap..topicref;       // the double colon enables retrieval of any <topicref> descendant.

for( i = 0; i < xmlTopicRefs.length( ); i++ )

{

     var sHref = xmlTopicRefs.@href.toString( );

     ... prepend the map's base path and check if the sHref points to an existing file ...

}

Note that the length property on an XML object does not exist - it is implemented as a length( ) function instead.

Also note that I have skipped the usual extensive error handling in the above code. You will be able to figure that out, no doubt.

Kind regards

Jang

FabianK007
Known Participant
May 29, 2018

Thank you Jang,

I used the codes from your answer and ran the script on a big file. Both versions took about 12 seconds. The commands you suggest are obviously more suitable but there is a thing I don't understand.

When using "oFile.open( 'r' )"  don't I open the file in FM anyway? Were you suggesting to use a standalone script?

Is the difference mainly in the memory usage? (I'm using the FM publishing server and I must process some files invisibly so the server does not crash)

Regards

Fabian

frameexpert
Community Expert
Community Expert
May 29, 2018

Jang's solution bypasses FrameMaker altogether. You are just using ExtendScript to process and check the XML files outside of FrameMaker.

www.frameexpert.com