• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

[FM10] Some support needed with book save as XML

Guest
Feb 14, 2013 Feb 14, 2013

Copy link to clipboard

Copied

Hi there,

I'm in a process to convert loads of old non structured FM manuals into structured formats, and though it all works fine there is a lot of repetition involved I'd like to get rid off. I'm having a bit of experience with extendscript for indesign, but the documentation for FM is rather poor. So if someone can get me started or provide some codesnippets to make my job a bit more pleasant it would be highly appreciated 🙂

My processes :

First I open a book, and for each file I run the 'Generate conversion Table' command. The missing paragraph tags need to be added to an existing Conversion table called 'conversion_table'.

Question 1 : Can I use some code to do this automatically ? So all fm files in the book get opened (silent or not does not really matter) , missing tags are added to the existing table, and fm file is closed again.

Second : I clean up the conversion table so output is a bit streamlined. That's a manual process anyway so no issues

Third : I structure the book using the table. Pretty straight forward also so no problem here

Last step : I save all fm files as docbook 2.1 format, but again this requires me to open all fm files one by one, select 'save as XML', select docbook as format and save the file itself.

Question 2 : Can I also here use some code so all fm files in the book are opened, saved as XML using docbook format , and closed again with me leaning back and looking at my PC doing the dirty job for me. To push my luck it would be great if I could also integrate step 3

I guess all of this would be rather simple for a seasoned programmer, but I'm cracking my teeth on it. Therefore anybody that can point me in the right direction or provide some code that could get me running would make my day for sure

Thanks in advance!

K.

TOPICS
Scripting

Views

2.1K

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
community guidelines

correct answers 1 Correct answer

Community Expert , Feb 18, 2013 Feb 18, 2013

I agree with Russ; you have a lot going on. I would suggest splitting your question into multiple posts, one for each step in the process. Most of us like to help, but I do this for a living so I can't spend too much time posting complete solutions for free. But here is some code that will automate your third step:

CallClient ("Structure Generator",  "InputDocId " + inputId);

CallClient ("Structure Generator",  "RuleDocId " + convId);

CallClient ("Structure Generator",  "StructureDoc");

The inputId

...

Votes

Translate

Translate
Mentor ,
Feb 18, 2013 Feb 18, 2013

Copy link to clipboard

Copied

Hi K,

Since nobody has responded, I thought I would add a little something, although probably not what you are asking for. Your requirements are well-suited for ExtendScript automation; however, they represent a fairly advanced usage of it. It could take some time to develop these scripts, more time than somebody can likely give you on a simple user-to-user forum post. So, I think that might be why you are having trouble getting responses.

This is a good place to ask specific questions about ES code, but yours is quite broad. I'm almost sure you would need to pay someone to write all that code. My suggestion is to back up a bit and start learning about ES at a lower level, then maybe  the way forward will eventually start to make more sense to you.

Russ

Votes

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
community guidelines
Community Expert ,
Feb 18, 2013 Feb 18, 2013

Copy link to clipboard

Copied

I agree with Russ; you have a lot going on. I would suggest splitting your question into multiple posts, one for each step in the process. Most of us like to help, but I do this for a living so I can't spend too much time posting complete solutions for free. But here is some code that will automate your third step:

CallClient ("Structure Generator",  "InputDocId " + inputId);

CallClient ("Structure Generator",  "RuleDocId " + convId);

CallClient ("Structure Generator",  "StructureDoc");

The inputId and convId variables are the id properties of the input document and the conversion table document, respectively. For example, if you are structuring the active document, you would do this to get the inputId:

var inputId = app.ActiveDoc.id;

There are also commands to add new entries to an existing conversion table. The best place to get this information is in the FDK manuals. You will have to "translate" the information from C to ExtendScript, but at least you have something to start with. I don't think any of the Structure Generator information is in the ExtendScript documentation.

Rick

Votes

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
community guidelines
Guest
Feb 18, 2013 Feb 18, 2013

Copy link to clipboard

Copied

Thanks both,

Fully understand and agree that I probably pushed my luck a bit 🙂

Let's try again on some part already. I'm able to run a script to save it as XML, and I probably can figure outhow to get it done on booklevel with the examples available, but I'm still struggling with the structured save part. Saving as XML works fine, and I found some example for the SDK, but I can't find the right syntax to do it on the extendscript Toolkit as that's a bit less intimidating for me.

This is what I have now :

var doc,  name, saveParams, i;

doc = app.ActiveDoc;

name = doc.Name;

fullName = name.replace(".fm",".xml");

saveParams = GetSaveDefaultParams();

returnParams = new PropVals();

i = GetPropIndex(saveParams, Constants.FS_FileType);

saveParams.propVal.ival =Constants.FV_SaveFmtXml;

i = GetPropIndex(saveParams, Constants.FS_StructuredSaveApplication);

saveParams.val.propVal.ival = "XDocBook"; <- this doesnt'work, any advice on what the exact syntax would be ?

doc.Save(fullName, saveParams, returnParams);

doc.Close(Constants.FF_CLOSE_MODIFIED);

Regards,

Koen

Votes

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
community guidelines
Community Expert ,
Feb 18, 2013 Feb 18, 2013

Copy link to clipboard

Copied

Since XDocBook is a string, it is probably .sval:

saveParams.val.propVal.sval = "XDocBook";

Votes

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
community guidelines
Guest
Feb 19, 2013 Feb 19, 2013

Copy link to clipboard

Copied

Actualy I was too fast with copy paste activity from c to extend, so after some tweeking I got this to work :

saveParams.propVal.sval = "XDocBook";

After some further playing around I got a full flow working now for the save as xml part, all files of the book are now opened silently, each document is saved with structured fomat and closed. Below full working code in case someone could use it also

------------------------------------------------------------------------

// Save all compontents as XML

bookTraverse ();

// Traverse through book components and save them when valid, thanks to the original creator !

function bookTraverse ()

{

var book = app.ActiveBook

    if (!book.ObjectValid() )

    {

       // kind reminder to select the book before we get started

        Alert ("Select book first" ,Constants.FF_ALERT_CONTINUE_WARN)

        return

     }

// Quick warning up front...   

var ret = Alert ("All files in this book will be saved as XML: Press <OK> to continue or <cancel> to abort",Constants.FF_ALERT_OK_DEFAULT)

if (ret == -1)

{

    return

}

var compBook = book.FirstComponentInBook

while(compBook.ObjectValid() )

{

    var compName = compBook.Name

    var compType = compBook.BookComponentFileType

    var doc = open(compName)

    if (compType == Constants.FV_BK_BOOK)

    {

        bookTraverse (doc)

     }

  if (doc.ObjectValid() )

  {

     // component is valid so we save as XML   

     saveDocAsXML (doc, doc.Name)

    doc.Close (1)

   }

    compBook = compBook.NextBookComponentInDFSOrder

}

Alert ("All are saved" ,Constants.FF_ALERT_CONTINUE_WARN)

}

function open(filename)

{

var openProp = GetOpenDefaultParams()

var i=GetPropIndex(openProp,Constants.FS_FileIsOldVersion)

openProp.propVal.ival=Constants.FV_DoOK

i=GetPropIndex(openProp,Constants.FS_FontNotFoundInCatalog)

openProp.propVal.ival=Constants.FV_DoOK

i=GetPropIndex(openProp,Constants.FS_FontNotFoundInDoc)

openProp.propVal.ival=Constants.FV_DoOK

i=GetPropIndex(openProp,Constants.FS_FileIsInUse)

openProp.propVal.ival=Constants.FV_DoCancel

i=GetPropIndex(openProp,Constants.FS_AlertUserAboutFailure)

openProp.propVal.ival=Constants.FV_DoCancel

i=GetPropIndex(openProp,Constants.FS_LockCantBeReset)

openProp.propVal.ival=Constants.FV_DoOK

i=GetPropIndex(openProp,Constants.FS_MakeVisible)

openProp.propVal.ival=false

var retParm = new PropVals()

var fileObj=Open(filename,openProp,retParm);

return fileObj

}

function saveDocAsXML(doc,name) {

var fullName = name.replace(".fm",".xml");

var saveParams = GetSaveDefaultParams();

var returnParams = new PropVals();

var i = GetPropIndex(saveParams, Constants.FS_FileType);

saveParams.propVal.ival =Constants.FV_SaveFmtXml;

i = GetPropIndex(saveParams, Constants.FS_StructuredSaveApplication);

saveParams.propVal.sval = "DocBook 2.1";

doc.Save(fullName, saveParams, returnParams);

}

Votes

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
community guidelines
Mentor ,
Feb 19, 2013 Feb 19, 2013

Copy link to clipboard

Copied

Koen,

You've done well! I think maybe you didn't really need help at all, maybe you just wanted to talk to somebody

Russ

Votes

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
community guidelines
Guest
Feb 19, 2013 Feb 19, 2013

Copy link to clipboard

Copied

Yeah, sometimes just thinking out loud get's you started also 🙂

Votes

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
community guidelines
Guest
Feb 19, 2013 Feb 19, 2013

Copy link to clipboard

Copied

Thanks Rick, this helped me quite a lot.

I was able to figure out how to add the missing entries to my conversion table using below mentioned booktraverser in combination with following :

function UpdateConvTable(doc,name,ConvTableID ){

// get current doc id

var docId = doc.id;

// add missing tags to conversion table

CallClient("Structure Generator", "SourceDocId " + docId);

CallClient("Structure Generator", "UpdateTable " + ConvTableID );

// and save the documents so it's up to date with latest version

var params = GetSaveDefaultParams();

var returnParamsp =new PropVals();

var i = GetPropIndex(params, Constants.FS_FileType);

params.propVal.ival =Constants.FV_SaveFmtBinary;

doc.Save(name, params, returnParamsp)

return

}

It does nicely what I want, it opens all the bookcomponents, adds the missing ones to my conversion table, saves the component and does all of this without nagging me with errors etc.

But..

I got the id of my conversion table by opening it, giving it the scope, and then retrieving the app.ActiveDoc.id. But this is a bit of unreliable method, for starters I'm not even sure if this id is unique and fixed, or can just be changed over time. What would therefore be a better to get the id of the conversion table, rather than having it hardcoded as I did now ?

Scenario I am thinking of is as follows

Book is selected, and script starts

-> if page with name "conversion_table" is not opened (using IsOnScreen ?), open the page (located at "C:\\conversion_table.fm)

-> if opened get the id , and run all code magic on all the book components (above function)

seems like fairly simple, but i can't find back any examples on how to use IsOnScreen, or opening a single document (my conversion table) without losing focus on selected book. Any advice / support would be welcome.

Votes

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
community guidelines
Community Expert ,
Feb 19, 2013 Feb 19, 2013

Copy link to clipboard

Copied

This may not be the best approach, but you could loop through the open documents and test its name to see if it is the conversion table. You should probably put this in a function.

var doc = app.FirstOpenDoc;

while (doc.ObjectValid() === 1) {

    if (/Conversion/.test(doc.Name) === true) {

        var convId = doc.id;

    }

    doc = doc.NextOpenDocInSession;

}

Rick

Votes

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
community guidelines
Guest
Feb 19, 2013 Feb 19, 2013

Copy link to clipboard

Copied

Thanks again Rick, it looks like a good alternative, but I'm not familiar with the /conversion/.test syntax.

I've tried a few things with above code, but it didn't give me results. Playing with the script I can get the name of the open docs etc, but the test thing puzzles me.

What would I need to change in (/Conversion/.test(doc.Name) === true) to make it work ? Assume I would have a document called conversion_table.fm, located at C:/folder/conversion_table.fm

Votes

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
community guidelines
Community Expert ,
Feb 19, 2013 Feb 19, 2013

Copy link to clipboard

Copied

This is where you get into core JavaScript versus FrameMaker ExtendScript. /Conversion/ is a JavaScript regular expression that matches the literal string "Conversion" somewhere in the file path or name. You can use /Conversion/i.test to give you a case-insensitive search; this is probably why it is failing for you. JavaScript has other ways of matching strings that you may find more convenient. I like the test method because it returns true or false.

Rick

Votes

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
community guidelines
Guest
Feb 19, 2013 Feb 19, 2013

Copy link to clipboard

Copied

ah, brilliant... the case insentive did the trick indeed.

Votes

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
community guidelines
Guest
Feb 20, 2013 Feb 20, 2013

Copy link to clipboard

Copied

Hi Expert,

I've tried above scripts, and thought it works great when updating the conversion table, it doesn't seem to do much when I want to structure my book. Below is the script I have, and I think i'm overlooking something obvious, as I believe that in theory it should work

function structureBook(){

   

     var bookID = app.ActiveBook.id;

     var bookName = app.ActiveBook.Name;

    

    //set path to current folder, and add struc

    var x=bookName.lastIndexOf("\\");

    var dirPath=bookName.substring(0, x )

    dirPath += "\\struc"

   

    //If no convTableId get it

       if(convTableId===0){

       getConvTableId();

    }

    //alert(convTableId + " - " + bookID  + " - "  + dirPath)

    //Structure current book using above values

    CallClient("Structure Generator", "InputBookId " + bookID);

    CallClient("Structure Generator", "RuleDocId " + convTableId);

    CallClient("Structure Generator", "OutputDirName " + dirPath);

    CallClient("Structure Generator", "GenerateBook");

    }

I get all my inputs correctly (book ID, Conversion table ID), the folder where I'd like to save the structured content does exist etc (anyway, commenting the outputdir part doesn't make a difference).

Yet nothing seems to happen, the script runs and gives no failure, but also no output. Any idea on what i might have missed (or how I could check where things go wrong ?)

Thanks again !

Votes

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
community guidelines
Mentor ,
Feb 20, 2013 Feb 20, 2013

Copy link to clipboard

Copied

Koen,

I could be wrong, but I don't think there is any such command as InputBookId. I think you need to go document-by-document with InputDocId.

Russ

Votes

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
community guidelines
Guest
Feb 20, 2013 Feb 20, 2013

Copy link to clipboard

Copied

Hi Russ, I found it in the FDK reference :

F_ApiCallClient() calls to structure a book

F_ApiCallClient("Structure Generator", "InputBookId objectID");

where objectID is the ID of the input book.

I know I can do it on document base, but then i need to generate the book again if i want to keep my original files, so it would be nice if i could get the book thing running

Votes

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
community guidelines
Mentor ,
Feb 20, 2013 Feb 20, 2013

Copy link to clipboard

Copied

Interesting. Never knew about that... I guess I never had a need. I've done it a single document at a time and it works.

Here is an idea, but it is a long shot. In some older versions of the FDK doc, there was a mistake where it said "GenerateDoc" instead of "StructureDoc", which caused the single doc conversion to fail. I see that the latest version of the FDK doc has fixed that, but it still says "GenerateBook" for the book conversion. I wonder if there is any chance that it should actually be "StructureBook"?  Maybe give that a try. If that doesn't work, I don't have any other suggestions at the moment. I'm a bit tied up to try it myself right now.

Votes

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
community guidelines
Guest
Feb 20, 2013 Feb 20, 2013

Copy link to clipboard

Copied

Haha, brilliant !  Using StructureBook indeed did the trick. Thanks a lot Russ

Votes

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
community guidelines
Mentor ,
Feb 20, 2013 Feb 20, 2013

Copy link to clipboard

Copied

Maybe not so brilliant, just that I've been around too long. Has it been that long?

Thanks for marking my answer as correct, but Rick definately deserves more credit. He was originally much more helpful than me.

Votes

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
community guidelines
Guest
Feb 20, 2013 Feb 20, 2013

Copy link to clipboard

Copied

LATEST

Yeah, it's a small annoyance of the system that you can't mark more than one correct answer. But you sure both helped me a lot !

Votes

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
community guidelines