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.
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.le
...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
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
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.
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).
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