Home > InDesign Scripts > Fill InDesign XMP info from document content

Fill InDesign XMP info from document content

A few days on Adobe’s InDesign Scripting forum I found question about inserting info into XMP InDesign file info. Also, mission was to find text formatted into specific paragraph style, and insert found content into XMP’s ‘Document Title’. Easiest way to achieve this is to use ‘Find’ and search for paragraph style. But, I also wanted to insert some more info into XMP like keywords or author, through scripting. So, I created document with some text from Adobe InDesign Features page, created two paragraph styles for Title and Author, and character style for keywords. So I formatted title and author with paragraph styles, and also I ran through text and formatted some words with ‘Keyword’ character style. So, let’s see how it works! 🙂

We will concentrate for now, just on document title, author and keywords. First, let’s take a look how to retrieve settings from document XMP.

var curDocTitle = app.activeDocument.metadataPreferences.documentTitle;
var curAuthor = app.activeDocument.metadataPreferences.author;
var curKeywords = app.activeDocument.metadataPreferences.keywords;

Document Title and Author are simple Strings, but Keywords is Array of Strings. We will use GREP find for all three cases. For Document Title and Author using just paragraph style search will be enough, but for keywords, we will combine character style search with GREP for searching words: \w{3,}. This will find words that are three or more characters long. We can increase or decrease depending on our needs, but keep in mind that you have to mark words you want to be in your keyword list with special character style, or if we get already prepared keywords, just mark them and we are good to go.
On the image, you can see how I did created my document. Of course, you don’t have to color your keywords separately.

So, first thing we need is little function to filter duplicate keywords. When we do GREP search, we will get Array of results, so we have to sort them alphabetically, and remove duplicates if there are any.

Array.prototype.unique = function (){
    var r = new Array();
    o:for(var i = 0, n = this.length; i < n; i++){
        for(var x = 0, y = r.length; x < y; x++){
            if(r[x]==this[i]) continue o;}
        r[r.length] = this[i];}
    return r;
}

Good. For easier usage, I created a short function, just to save time needed for implementation and reuse. For more info, read comment lines inside function.

function addXMP(/*find GREP*/findString, /*para style*/paraStyle, /*chr style*/chrStyle, /*insert to*/XMPdest){
  // reset search fields
  app.findGrepPreferences = NothingEnum.nothing;
  app.changeGrepPreferences = NothingEnum.nothing;
  // setting search parameters
  if(findString)app.findGrepPreferences.findWhat = findString;
  if(paraStyle)app.findGrepPreferences.appliedParagraphStyle = paraStyle;
  if(chrStyle)app.findGrepPreferences.appliedCharacterStyle = chrStyle;

  switch (XMPdest){
    // insert keywords
    case "Keywords":
      var myKeywords = app.activeDocument.findGrep();
      var myKeys = Array();
      // loop through keywords and get contents
      for(var i = 0; i < myKeywords.length; i++)
        myKeys.push(myKeywords[i].contents);
      myKeys.sort();
      // delete duplicates
      myKeys = myKeys.unique();
      // insert Keywords to document XMP
      app.activeDocument.metadataPreferences.keywords = myKeys;
      break;
    // Heading search/insert
    case "Heading":
      var myHeading = app.activeDocument.findGrep();
      app.activeDocument.metadataPreferences.documentTitle = myHeading[0].contents;
      break;
    // Author search/insert
    case "Author":
      var myAuthor = app.activeDocument.findGrep();
      app.activeDocument.metadataPreferences.author = myAuthor[0].contents;
      break;
  }
}

And now let’s see how to use this little function:

// add Keywords
addXMP("\\w{3,}","","KeywordsCStyle","Keywords");

// add Heading
addXMP("","HeadingPStyle","","Heading");

//add Author
addXMP("","AuthorPStyle","","Author");

An the final result looks like this:

Also, if you we want to have all keywords in lowercase, we can just alter line 17 in function to this:

    myKeys.push(myKeywords[i].contents.toLowerCase());

If we have more than one author, we can simply loop through search results and combine them into one String. Also, you may noticed, other empty fields: Author Title, Description, Description Writer, Copyright Notice, Copyright Info URL, Copyright Status and Rating. Some of them we can change really easily, but for some of them, we have to dig little deeper into metadata Class. I will just briefly show few examples how to change some of them, and if you are interested in adding Rating, Author Title or Description Writer, feel free to contact me.

var myDescription = app.activeDocument.metadataPreferences.description;
var myCopyrightNotice = app.activeDocument.metadataPreferences.copyrightNotice;
var myCopyrightInfoURL = app.activeDocument.metadataPreferences.copyrightInfoURL;
var myCopyrightStatus = app.activeDocument.metadataPreferences.copyrightStatus;

All properties except copyrightStatus are Strings. For copyrightStatus we have following options:

Value Description
CopyrightStatus.UNKNOWN The copyright status is unknown. (Default)
CopyrightStatus.NO The document is in the public domain.
CopyrightStatus.YES The document is copyrighted.

So, that’s it!

Have fun! 😀

  1. August 31, 2010 at 23:07

    Hi tomaxxi,

    Good snippet!

    Another to filter duplicates is to use ‘associative array’, which avoid re-looping:

    Array.prototype.unique = function ()
    {
    var i, a = {},r = [],
    n = this.length;
    for( i=0 ; i<n ; ++i ) a[this[i]]=1;
    for( i in a ) r.push(i);
    return r;
    }

    alert( ['aa','bb','aa','cc',12,5,12].unique() );
    // aa,bb,cc,12,5

    • August 31, 2010 at 23:14

      Hey Marc!

      Thanks! And thank you for excellent function! 😉

      tomaxxi

  2. September 2, 2010 at 14:39

    I sometimes wondered if it would be possible to add custom toggle (or more precisely other xml nodes).
    I thought it my be a convenient place to store some infos we might want to keep about the document. That in order to reuse these datas in scripting.
    I imagine, maybe, what about the genuine dimensions dimensions,etc.

    But then, I saw a post on the scripting forum about insertLabel(). Using that command seems to offer this opportunity.

    Anyway, the discussion is open.

    Loic

    • September 2, 2010 at 14:56

      It’s possible to create custom nodes for example in “http://ns.adobe.com/xap/1.0/” namespace. It’s really easy to achieve… 🙂 Maybe I will write some short post about it… 😉

  1. August 31, 2010 at 22:21
  2. September 7, 2010 at 01:58
  3. June 1, 2011 at 14:19

Leave a comment