Highlighted

Verify References in a Ditamap - ExtendScript

Explorer ,
May 29, 2018

Copy link to clipboard

Copied

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

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

TOPICS
Scripting

Views

243

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Verify References in a Ditamap - ExtendScript

Explorer ,
May 29, 2018

Copy link to clipboard

Copied

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

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

TOPICS
Scripting

Views

244

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
May 29, 2018 0
Advocate ,
May 29, 2018

Copy link to clipboard

Copied

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

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
May 29, 2018 0
Explorer ,
May 29, 2018

Copy link to clipboard

Copied

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

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
May 29, 2018 0
Adobe Community Professional ,
May 29, 2018

Copy link to clipboard

Copied

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

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
May 29, 2018 1
Advocate ,
May 29, 2018

Copy link to clipboard

Copied

As Rick remarked but clarifying a bit more - opening the file as text in ExtendScript bypasses the rendering engine of FrameMaker, which also includes all kinds of cross-reference checking etc. As you are not interested in rendering unless all topicrefs point to actual files, running that check does not require opening the actual files.

BTW, if you are using the DITA-OT route to render the ditamap (which is an option in FrameMaker as well as the Fm Pub Server), Frame will not open the files at all, but run the DITA-OT transforms instead. But I am assuming you use the FrameMaker rendering engine for your output(s).

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
May 29, 2018 1
Explorer ,
May 30, 2018

Copy link to clipboard

Copied

Good afternoon gentlemen,

Thank you again. I'm pretty sure we are using the FrameMaker rendering engine, although I don't understand everything of what our scripts are doing.

Anyway, I made a mistake yesterday while implementing your suggestion. It is 200ms fast, not 12s like mine

Regards

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
May 30, 2018 0