Working with DITA Publishing

This topic provides the following DITA publishing-related tasks and code examples:

Setting Up a DITA Project

Use the following steps to set up DITA Publishing and verify that it is working correctly. You will need a DITA project (DITA topics and maps) to complete this task.

Note: For testing purposes, you can find a simple DITA project in the DITA Open Toolkit's samples directory.

  1. Retrieve the DITA Open Toolkit from http://sourceforge.net/projects/dita-ot/ and expand the package (.zip or .tar.gz) to the desired installation directory on either the Content Engine server or a server that is mapped/mounted on the Content Engine server. For example, you could expand the archive to the c:\DITA-OT1.4.2.1 directory on the Content Engine server.
  2. Install the DITA Publishing Extensions. From the IBM® FileNet® Enterprise Manager, right-click on the object store where you want to install the add-on and choose All Tasks > Install AddOn. Then, select DITA Publishing Extensions (dependent add-ons will be automatically selected) and click Install.
  3. Optionally, make one or more of the following customizations. See Customizing DITA Publishing for details.
  4. If you customized DITA Publishing (as described in the previous step), set up the customized DITA classifier. See Setting up the DITA Classifier.
  5. Optionally, modify the DITA Open Toolkit to support a DITA specialization or a custom rendering plug-in. See the DITA Open Toolkit documentation for instructions.
  6. Optionally, create a p8dita.env file to specify the DITA Open Toolkit environment. See Creating a p8dita.env File.
  7. Create a DITARenditionEngineConnection object. To complete this task, you can use either the IBM FileNet Enterprise Manager (see Work with the Rendition Engine Connections) or the Content Engine API (see Creating a DITARenditionEngineConnection Object).
  8. Create a publish style template. To complete this task, you can use either the Publishing Style Template Manager (see Add or modify DITA rendition engine style templates) or the Content Engine API (see Creating a Publish Style Template for DITA).
  9. Create a publish template. To complete this task, you can use either IBM FileNet P8 Workplace (see Create publishing templates) or the Content Engine API (see Creating a Publish Template for DITA).
  10. Check in your DITA project. You can check in the files manually (using IBM FileNet Enterprise Manager) or you can write a program to import an entire DITA project. A sample DITA importer is provided through the IBM support page. To download the sample, see Accessing IBM FileNet Documentation.
  11. Publish the DITA project using the copy-only option. To complete this task, you can use either IBM FileNet P8 Workplace (see Publish your first document) or the Content Engine API (see Publishing a DITA Project). Once the publish operation is complete, verify that all of the imported DITA project files were copied to the working directory. Also, check for missing references by searching the project files in the working directory for 0-length files.
  12. Publish the project again, but this time set the "copy-only" option to false and choose PDF as the transformation type. Verify that the PDF is generated and checked in as expected. If the publish operation fails, check the log file located in the publish folder of your DITA working directory (for example, c:\ditatemp\ditapr-23445\my_project_pdf.log).

Customizing DITA Publishing

This topic describes an example scenario for customizing DITA Publishing. The scenario includes the following customizations:

Note: The DITA classifier Java™ source code (DITAClassifier.java) is provided through the IBM support page. To download the source code, see Accessing IBM FileNet Documentation. Once you have completed all of your DITA Publishing customizations, you will need to compile this code and then set up the customized DITA classifier (as described in Setting up the DITA Classifier).

Adding support for DITA long quote (<lq>) references

  1. Add a DitaLqref class to DitaBaseref.
    1. From the IBM FileNet Enterprise Manager, select Object Stores > object_store_name > Other Classes > Component Relationship > DitaBaseref.
    2. From the Action menu, choose New Class. The "Create a Class Wizard" displays.
    3. Click Next.
    4. On the "Name and Describe the Class" page:
      1. Enter a Name: DitaLqref
      2. Enter a Symbolic Name: DitaLqref
      3. Enter a Description: DITA long quote component relationship
      4. Click Next.
    5. On the "Select Properties" page, click Next. (You do not need to add any properties.)
    6. On the "Select Property Attributes" page, click Next. (You do not need to set any property attributes at the class level.)
    7. On the "Configure Auditing" page, click Next. (You do not need to specify any events.)
    8. Click Finish.
  2. In the DITA classifier, add a line supporting the DitaLqref class in three places, as shown below.

    Place 1

    public static final String DITABASEREF_CLASS   = "DitaBaseref"; 
    public static final String DITATOPICREF_CLASS  = "DitaTopicref"; 
    public static final String DITAMAPREF_CLASS    = "DitaMapref"; 
    public static final String DITAIMAGEREF_CLASS  = "DitaImageref"; 
    public static final String DITACONREF_CLASS    = "DitaConref"; 
    public static final String DITAXREF_CLASS      = "DitaXref"; 
    public static final String DITALINKREF_CLASS   = "DitaLinkref";
    public static final String DITALQREF_CLASS     = "DitaLqref";    // customization
    

    Place 2

    // map DITA reference types to P8 component relationship classes
    //
    // Customization point: If defining new DITA relationship types,
    // add them and their corresponding P8 component relationship classes here
    hrefMap = new HashMap();        
    hrefMap.put("topic", DITATOPICREF_CLASS);
    hrefMap.put("xref",  DITAXREF_CLASS);
    hrefMap.put("image", DITAIMAGEREF_CLASS);
    hrefMap.put("conref", DITACONREF_CLASS);
    hrefMap.put("link", DITALINKREF_CLASS);
    hrefMap.put("lq", DITALQREF_CLASS);    // customization
    

    Place 3

    // Map P8 component relationship class names to relationship names
    //
    // Customization point: If defining new DITA relationship types,
    // add them and their display names here
    relationshipNameMap = new HashMap();        
    relationshipNameMap.put(DITATOPICREF_CLASS, "DITA topicref relationship");
    relationshipNameMap.put(DITAXREF_CLASS, "DITA xref relationship");
    relationshipNameMap.put(DITAIMAGEREF_CLASS, "DITA image relationship");
    relationshipNameMap.put(DITACONREF_CLASS, "DITA conref relationship");
    relationshipNameMap.put(DITALINKREF_CLASS, "DITA link relationship");
    relationshipNameMap.put(DITALQREF_CLASS, "DITA long quote relationship");    // customization
    
  3. If this is the last customization you intend to make, compile the DITA classifier.

Adding support for the DITA messaging specialization

  1. Add a DitaMsg class to DitaBaseref.
    1. From the IBM FileNet Enterprise Manager, select Object Stores > object_store_name > Document Class > DitaBase.
    2. From the Action menu, choose New Class. The "Create a Class Wizard" displays.
    3. Click Next.
    4. On the "Name and Describe the Class" page:
      1. Enter a Name: DitaMsg
      2. Enter a Symbolic Name: DitaMsg
      3. Enter a Description: DITA messaging document
      4. Click Next.
    5. On the "Select Properties" page, click Next. (You do not need to add any properties.)
    6. On the "Select Property Attributes" page, click Next. (You do not need to set any property attributes at the class level.)
    7. On the "Configure Auditing" page, click Next. (You do not need to specify any events.)
    8. Click Finish.
  2. In the DITA classifier, add a line supporting the DitaMsg class in two places, as shown below.

    Place 1

    public static final String DITAMAP_CLASS       = "DitaMap"; 
    public static final String DITABOOKMAP_CLASS   = "DitaBookMap"; 
    public static final String DITACONCEPT_CLASS   = "DitaConcept";
    public static final String DITAMSG_CLASS       = "DitaMsg";     // customization
    public static final String DITAREFERENCE_CLASS = "DitaReference"; 
    public static final String DITATASK_CLASS      = "DitaTask"; 
    public static final String DITATOPIC_CLASS     = "DitaTopic"; 
    public static final String DITABASE_CLASS      = "DitaBase";
    

    Place 2

    // map DITA types to P8 document classes
    //
    // Customization point: If defining new DITA types,
    // add them and their corresponding P8 document classes here
    ditatypeMap = new HashMap();
    ditatypeMap.put("map", DITAMAP_CLASS);
    ditatypeMap.put("bookmap", DITABOOKMAP_CLASS);
    ditatypeMap.put("concept", DITACONCEPT_CLASS);
    ditatypeMap.put("msg", DITAMSG_CLASS);    // customization
    ditatypeMap.put("reference", DITAREFERENCE_CLASS);
    ditatypeMap.put("task", DITATASK_CLASS);
    ditatypeMap.put("topic", DITATOPIC_CLASS);
    ditatypeMap.put("dita", DITABASE_CLASS);
    ditatypeMap.put("glossentry", DITAGLOSSENTRY_CLASS);
    
  3. If this is the last customization you intend to make, compile the DITA classifier.

Adding support for the DitaCopyrightHolder property

  1. Add a property template for DitaCopyrightHolder:
    1. From the IBM FileNet Enterprise Manager, select Object Stores > object_store_name > Property Templates.
    2. From the Action menu, choose New Property Template. The "Create a Property Template Wizard" displays.
    3. Click Next.
    4. On the "Name and Describe the Property Template" page:
      1. Enter a Name: DitaCopyrightHolder
      2. Enter a Symbolic Name: DitaCopyrightHolder
      3. Enter a Description: DITA copyright holder
      4. Click Next.
    5. On the "Select the Data Type" page, choose String and click Next.
    6. On the "Select a Choice List" page, click Next. (You do not need to specify a choice list.)
    7. On the "Single or Multi-Value?" page:
      1. Select Multi.
      2. Select Unique and unordered values.
      3. Enter a Description: DITA copyright holder
      4. Click Next.
    8. Click Finish.
  2. Add the DitaCopyrightHolder property to the DitaBase class.
    1. From the IBM FileNet Enterprise Manager, select Object Stores > object_store_name > Document Class > DitaBase.
    2. From the Action menu, choose Add Properties to Class. The "Add Properties to a Class Wizard" displays.
    3. Click Next.
    4. On the "Select Properties" page:
      1. Select DitaCopyrightHolder from the Available list.
      2. Click Add.
      3. Click Next.
    5. On the "Select Property Attributes" page, click Next. (You do not need to set property attributes at the class level.)
    6. Click Finish.
  3. In the DITA classifier, add a line that supports the DitaCopyrightHolder property, as shown below.
    // Non ditamap or bookmap types
    // Customization point: Add or remove properties here
    // If property string length is not default, pass in length of string property here to truncate
    addProperty(propertiesMap, "DitaId", getProperty(nMap, "id", MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaTitle", getProperty("/" + rootElementName + "/title", MAX_DEFAULT_METADATA_STRING_SIZE));
    
    addProperty(propertiesMap, "DitaAudiences", getMultiValueProperties("//audience/@type", MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaAuthors", getMultiValueProperties("//author", MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaBrands", getMultiValueProperties("//brand", MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaCategories", getMultiValueProperties("//category", MAX_DEFAULT_METADATA_STRING_SIZE));
    // customization
    addProperty(propertiesMap, "DitaCopyrightHolder", getMultiValueProperties("//copyrholder", MAX_DEFAULT_METADATA_STRING_SIZE));
    // end customization
    addProperty(propertiesMap, "DitaKeywords", getMultiValueProperties("//keyword", MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaNavTitle", getProperty("/" + rootElementName + "/titlealts/navtitle", MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaPlatforms", getMultiValueProperties("//platform", MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaProdNames", getMultiValueProperties("//prodname", MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaSearchTitle", getProperty("/" + rootElementName + "/titlealts/searchtitle", MAX_DEFAULT_METADATA_STRING_SIZE));
    
  4. If this is the last customization you intend to make, compile the DITA classifier.

Removing support for the DitaBrands property

  1. Remove the DitaBrands property from the DitaBase class.
    1. From the IBM FileNet Enterprise Manager, select Object Stores > object_store_name > Document Class > DitaBase.
    2. From the Action menu, choose Add Properties to Class. The "Add Properties to a Class Wizard" displays.
    3. Click Next.
    4. On the "Select Properties" page:
      1. Select DitaBrands from the Selected list.
      2. Click Remove.
      3. Click Next.
    5. On the "Select Property Attributes" page, click Next. (You do not need to set property attributes at the class level.)
    6. Click Finish.
  2. In the DITA classifier, comment out the line that adds the DitaBrands property, as shown below.
    // Customization point: Add or remove properties here
    // If property string length is not default, pass in length of string property here to truncate
    addProperty(propertiesMap, "DitaId", getProperty(nMap, "id", REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));  
    List list =  getMultiValueProperties("//keyword", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE);
    addProperty(propertiesMap, "DitaKeywords", list);
    addProperty(propertiesMap, "DitaAuthors", getMultiValueProperties("//author", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    // addProperty(propertiesMap, "DitaBrands", getMultiValueProperties("//brand", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaCategories", getMultiValueProperties("//category", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaPlatforms", getMultiValueProperties("//platform", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaAudiences", getMultiValueProperties("//audience/@type", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaProdNames", getMultiValueProperties("//prodname", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaNavTitle", getProperty("/" + rootElementName + "/titlealts/navtitle", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaSearchTitle", getProperty("/" + rootElementName + "/titlealts/searchtitle", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    addProperty(propertiesMap, "DitaTitle", getProperty("/" + rootElementName + "/title", NOT_REQUIRED, MAX_DEFAULT_METADATA_STRING_SIZE));
    
  3. If this is the last customization you intend to make, compile the DITA classifier.

Enabling cascade delete for relationships created by the DITA classifier

  1. In the DITA classifier, set the ComponentCascadeDelete property value to CASCADE_DELETE, as shown below.
    // Customization point: Modify behavior of component relationship objects here
    relationshipCounter++;
    int sortOrder = BASE_COMPONENT_SORT_NUM * relationshipCounter;
    cr.set_ChildComponent(child);   
    cr.set_VersionBindType(VersionBindType.LATEST_MAJOR_VERSION);
    cr.set_CopyToReservation(Boolean.FALSE);
    // customization
    cr.set_ComponentCascadeDelete(ComponentCascadeDeleteAction.CASCADE_DELETE)
    // end customization
    cr.set_ComponentSortOrder(new Integer(sortOrder));
    
  2. If this is the last customization you intend to make, compile the DITA classifier.

Changing the default length of string properties from 64 to 80 characters

Note: You must perform this procedure before you create any Document instances that use the updated properties.

  1. Change the Maximum Length String property for DITA properties.
    1. From the IBM FileNet Enterprise Manager, select Object Stores > object_store_name > Property Templates.
    2. Right-click on DitaAudiences and choose Properties. The "DitaAudiences Properties" dialog box displays.
    3. On the Properties tab, change the Maximum Length String property to 80.
    4. Click OK.
    5. Repeat this step for the remaining DITA properties that have a data type of string.
  2. In the DITA classifier, change the value of MAX_DEFAULT_METADATA_STRING_SIZE to 80, as shown below.
    private static final int MAX_DEFAULT_METADATA_STRING_SIZE = 80;
    
  3. If this is the last customization you intend to make, compile the DITA classifier.

Setting up the DITA Classifier

If you plan to use a customized DITA classifier, perform the following procedures.

Creating a DITA Classifier Code Module

  1. From the IBM FileNet Enterprise Manager, select Object Stores > object_store_name > Root Folder > CodeModules.
  2. If a DITA Classifier action already exists, either delete it or change its MIME type so that it isn't called when a DITA document is checked in.
  3. From the Action menu, choose New Document. The "Create New Document Wizard" displays.
  4. On the "Create a document object" page:
    1. Enter a document title (for example, Custom DITA Classifier).
    2. Select the With content radio button.
    3. Leave the Save As Reservation, Create Minor Version, and Create as Compound Document options unchecked.
    4. Click Next.
  5. On the "Document Content Type and Source" page:
    1. Browse to or enter the location of your customized DITA classifier (DITAClassifier.class).
    2. Check the Reference box for DITAClassifier.class. The Change MIME type button is enabled.
    3. Click Change MIME type.
    4. Enter "application/java" (without the quotes) as the new MIME type and click OK.
    5. Uncheck the Reference box for DITAClassifier.class.
    6. In the "Document MIME Type" field, enter "application/java" (without the quotes).
    7. Click Next.
  6. On the "Class and Properties" page:
    1. Check the List hidden classes option.
    2. From the Class drop-down menu, choose Code Module.
    3. Click Next.
  7. On the "Advanced Features" page, click Finish. (No changes are required to any of the default values.)

Creating a DITA Classifier Document Classification Action

  1. From the IBM FileNet Enterprise Manager, select Object Stores > object_store_name > Document Classification Actions.
  2. From the Action menu, choose New Document Classification Action. The "Create a Document Classification Action Wizard" displays.
  3. Click Next.
  4. On the "Name and Describe the Document Classification Action" page:
    1. Enter a unique name (for example, Custom DITA Classifier).
    2. Enter a description.
    3. Click Next.
  5. On the "Enter Class and MIME Type" page:
    1. Enter the following MIME Type: application/dita+xml
    2. Click Next.

    Note: This setting means that the DITA classifier will only be invoked on documents with a mime type of application/dita+xml.

  6. On the "Specify the Type of Document Classification Action" page:
    1. Enter the following Event Action Handler Java Class Name: com.filenet.engine.queueitem.DITAClassifier
    2. Check the Configure Code Module option.
    3. Click Next.
  7. On the "Specify the Code Module to be configured" page:
    1. Click Load Existing and select the code module you created in the previous procedure (for example, Custom DITA Classifier).
    2. Click Next. (You do not need to make any changes to the Content Elements section of the wizard page.)
  8. Click Finish. You should see a message box that says: "You have successfully created the 'Custom DITA Classifier' document classification action."

Creating a p8dita.env File

To statically define the DITA Open Toolkit invocation environment:

  1. Create a file named p8dita.env.
  2. Edit the file to include the CLASSPATH, ANT_HOME, and PATH environment variables.
  3. Save the file to the top-level DITA Open Toolkit installation directory (for example, c:\DITA-OT1.4.2.1).

A Microsoft® Windows example of the p8dita.env file is shown below. Note that the lines CLASSPATH, ANT_HOME and PATH must each be on a single, separate line. (They are shown on multiple lines here for clarity.)

p8dita.env Example

CLASSPATH=e:\DITA-OT1.4\lib\avalon-framework-cvs-20020806.jar;
    e:\DITA-OT1.4\lib\batik.jar;e:\DITA-OT1.4\lib\dost.jar;
    e:\DITA-OT1.4\lib\fop.jar;e:\DITA-OT1.4\lib\icu4j.jar;
    e:\DITA-OT1.4\lib\resolver.jar;e:\DITA-OT1.4\lib\xalan.jar;
    e:\DITA-OT1.4\lib\xercesImpl.jar;e:\DITA-OT1.4\lib\xml-apis.jar;
    e:\DITA-OT1.4C:\WINDOWS\system32;
ANT_HOME=e:\DITA-OT1.4\tools\ant
PATH=e:\DITA-OT1.4\tools\ant\bin;
E:\Program Files\IBM\WebSphere\AppServer\java\bin;%PATH%

Navigating DITA Relationships

The code example below traverses and displays the compound document structure of a DITA document. The output format is:

    /[Component relationship class] => [Document class]: [Document title] [Document id]

For example:

   /DitaTopicref => DitaConcept: Lawnmower {78C7186D-5DB6-462A-8F91-B461A7C01870}

Where the child document's title is "Lawnmower", the class that represents the component relationship between the child and parent documents is DitaTopicref, and the child document's class is DitaConcept.

The code also detects circular relationships. If one of the parent components shown for a document is itself, "[circular reference]" is displayed next to the child document.

For information on compound documents, see Compound Documents. For information on DITA-specific relationships, see DITA Relationships.

Java Example

private static void navigateDitaStructure(
        Document rootParent)
{
    traverseCompoundDocument(rootParent, null, 0, null,
                            "DitaTitle", "DocumentTitle");
}

// Traverse compound document structure
private static void traverseCompoundDocument(
        Document parent, 
        ComponentRelationship crParent, // Component relationship to parent (null on first call)
        int level,                      // Indentation level (zero on first call)
        HashMap circRefMap,             // Circular reference checking (null on first call)
        String... titlePropName)        // Document title property name(s)
{
    
    // Initialize message
    String message = "";
    
    // Indent based on document level
    for (int count = 0; count < level; count++)
    {
        message += "    ";
    }
    message += "/";
    
    // Show type of component relationship
    if (crParent != null)
    {
        message += crParent.getClassName() + " => ";
    }
    
    // Show document title
    String title = getDocTitle(parent, titlePropName);
    if (title == null)
    {
        title = "???";
    }
    message += parent.getClassName() + ": " + title + " " + parent.get_Id();

    // Create map for circular reference checking 
    if (circRefMap == null)
    {
        circRefMap = new HashMap();
    }

    // Check for circular reference
    boolean circRef = false;
    String parentKey = parent.get_Id().toString();
    if (circRefMap.containsKey(parentKey) == true)
    {
        circRef = true;
        message += " [circular reference]";
    }
    circRefMap.put(parentKey, parent);
    
    // Output message
    System.out.println(message);
    if (circRef == true)
    {
        return;
    }
        
    // Iterate through child documents
    ComponentRelationshipSet crSet = parent.get_ChildRelationships();
    Iterator iter = crSet.iterator();
    while(iter.hasNext())
    {
        // Make recursive call
        ComponentRelationship crChild = (ComponentRelationship) iter.next();
        Document child = crChild.get_ChildComponent();
        if (child != null)
        {
            traverseCompoundDocument(child, crChild, level + 1, circRefMap, titlePropName);
        }
    }   
            
    // Remove document from circular reference map
    circRefMap.remove(parentKey);
    
}

// Get document title
private static String getDocTitle(
        Document doc,
        String... propName)
{

    String title = null;
    doc.refresh();
    for (String titlePropName : propName)
    {
        if (doc.getProperties().isPropertyPresent(titlePropName) == true)
        {
            title = doc.getProperties().get(titlePropName).getStringValue();
            if (title != null)
            {
                break;
            }
        }
    }
    return title;    
}

C# Example

private static void NavigateDitaStructure(
        IDocument rootParent)
{
    TraverseCompoundDocument(rootParent, null, 0, null,
                        "DitaTitle", "DocumentTitle");
}

// Traverse compound document structure
private static void TraverseCompoundDocument(
        IDocument parent, 
        IComponentRelationship crParent,    // Component relationship to parent (null on first call)
        int level,                          // Indentation level (zero on first call)
        Hashtable circRefMap,               // Circular reference checking (null on first call)
        params String[] titlePropName)      // Document title property name(s)
{

    // Initialize message
    String message = "";

    // Indent based on document level
    for (int count = 0; count < level; count++)
    {
        message += "    ";
    }
    message += "/";

    // Show type of component relationship
    if (crParent != null)
    {
        message += crParent.GetClassName() + " => ";
    }

    // Show document title
    String title = GetDocTitle(parent, titlePropName);
    if (title == null)
    {
        title = "???";
    }
    message += parent.GetClassName() + ": " + title + " " + parent.Id;

    // Create map for circular reference checking 
    if (circRefMap == null)
    {
        circRefMap = new Hashtable();
    }

    // Check for circular reference
    Boolean circRef = false;
    String parentKey = parent.Id.ToString();
    if (circRefMap.ContainsKey(parentKey) == true)
    {
        circRef = true;
        message += " [circular reference]";
    }
    if (circRefMap.ContainsKey(parentKey) == false)
    {
        circRefMap.Add(parentKey, parent);
    }

    // Output message
    Debug.WriteLine(message);
    if (circRef == true)
    {
        return;
    }
    
    // Iterate through child documents
    IComponentRelationshipSet crSet = parent.ChildRelationships;
    foreach (IComponentRelationship crChild in crSet)
    {
        // Make recursive call
        IDocument child = crChild.ChildComponent;
        if (child != null)
        {
            TraverseCompoundDocument(child, crChild, level + 1, circRefMap, titlePropName);
        }
    }   
        
    // Remove document from circular reference map
    circRefMap.Remove(parentKey);

}

// Get document title
private static String GetDocTitle(
        IDocument doc,
        params String[] propName)
{
    String title = null;
    doc.Refresh();
    foreach (String titlePropName in propName)
    {
        if (doc.Properties.IsPropertyPresent(titlePropName) == true)
        {                
            title = (String) doc.Properties[titlePropName];
            if (title != null)
            {
                break;
            }
        }
    }
    return title;    
}

Searching for DITA Metadata

The code example below illustrates how to perform a simple query for DITA documents based on property values. The class queried against, DitaBase, is the parent class for all of the DITA document subclasses that represent the standard DITA information types (concept, glossentry, reference, task, and topic).

For background information on performing queries, see Queries. For additional information on querying DITA documents, see DITA Query.

Java Example

public static void queryDitaAuthor(
        ObjectStore objStore,
        String userName)
{
    // Construct SQL object
    SearchSQL sqlObject = new SearchSQL();
    sqlObject.setSelectList("db.DitaTitle, db.Id");
    sqlObject.setFromClauseInitialValue("DitaBase", "db", true);
    sqlObject.setWhereClause("IsCurrentVersion = true "
                             + "AND '" + userName + "' IN db.DitaAuthors");        
    System.out.println("SQL: " + sqlObject.toString()); 

    // Execute the query
    SearchScope search = new SearchScope(objStore);
    RepositoryRowSet queryRows = search.fetchRows(
            sqlObject, new Integer(10), null, new Boolean(true));

    // Iterate through the returned rows
    int rowCount = 0;
    Iterator iter = queryRows.iterator();
    while (iter.hasNext()) 
    {
        RepositoryRow row = (RepositoryRow) iter.next();
            
        String ditaTitle 
                = row.getProperties().get("DitaTitle").getStringValue();
        Id docId = row.getProperties().get("Id").getIdValue();
            
        rowCount++;
        System.out.print(" row " + rowCount + ":");
        System.out.print(" Id=" + docId.toString());
        if (ditaTitle != null) 
        {
            System.out.print(" DitaTitle=" + ditaTitle);
        }
        System.out.println();                                    
    }            
    if (rowCount == 0)
    {
        System.out.println("No rows returned for query");
    }
    
}

C# Example

public static void queryDitaAuthor(
        IObjectStore objStore,
        String userName)
{
    // Construct SQL object
    SearchSQL sqlObject = new SearchSQL();
    sqlObject.SetSelectList("db.DitaTitle, db.Id");
    sqlObject.SetFromClauseInitialValue("DitaBase", "db", true);
    sqlObject.SetWhereClause("IsCurrentVersion = true "
                         + "AND '" + userName + "' IN db.DitaAuthors");        
    Debug.WriteLine("SQL: " + sqlObject.ToString()); 

    // Execute the query
    SearchScope search = new SearchScope(objStore);
    IRepositoryRowSet queryRows = search.FetchRows(
            sqlObject, 10, null, true);

    // Iterate through the returned rows
    int rowCount = 0;
    foreach (IRepositoryRow row in queryRows)
    {
        String ditaTitle 
                = row.Properties
                  .GetProperty("DitaTitle").GetStringValue();
        Id docId = row.Properties.GetProperty("Id").GetIdValue();
            
        rowCount++;
        Debug.Write(" row " + rowCount + ":");
        Debug.Write(" Id=" + docId.ToString());
        if (ditaTitle != null) 
        {
            Debug.Write(" DitaTitle=" + ditaTitle);
        }
        Debug.WriteLine("");                                    
    }            
    if (rowCount == 0)
    {
        Debug.WriteLine("No rows returned for query");
    }

}

The code example below illustrates how to find all of the parent documents for a particular child document. This query would be useful, for instance, when attempting to determine all of the topics that reference a particular DITA topic.

Java Example

public static void queryDitaComponent(
        ObjectStore objStore,
        String childVerSeriesId,    // Child document version series id
        String tableName,           // Example: "DitaTopicref" or "DitaConref"
        String propName,            // Example: "DitaId" or "DitaElementId"
        String propValue)           // Property value
{
    // Show parameters
    System.out.println("Parameter childVerSeriesId: " + childVerSeriesId);
    System.out.println("Parameter tableName: " + tableName);
    System.out.println("Parameter propName: " + propName);
    System.out.println("Parameter propValue: " + propValue);
    System.out.println("");
    
    // Construct SQL object
    // Note: "ChildComponent" could be used in the SQL below instead of
    // "ChildVersionSeries" to query for a specific child docuument. The
    // query below catches all component relationships that bind to any 
    // document within the child version series.
    SearchSQL sqlObject = new SearchSQL();
    sqlObject.setSelectList("d.id, d.DitaTitle"); 
    sqlObject.setFromClauseInitialValue("Document", "d", true);
    sqlObject.setFromClauseAdditionalJoin(JoinOperator.INNER, tableName, "cr", "d.This", JoinComparison.EQUAL, "cr.ParentComponent", false);
    sqlObject.setWhereClause("cr.ChildVersionSeries = OBJECT(" + childVerSeriesId + ") "
                             + "AND cr." + propName + " = '" + propValue + "'");
    System.out.println("SQL: " + sqlObject.toString()); 
    
    // Execute the query
    SearchScope search = new SearchScope(objStore);
    RepositoryRowSet queryRows = search.fetchRows(
            sqlObject, new Integer(10), null, new Boolean(true));

    // Iterate through the returned rows
    int rowCount = 0;
    Iterator iter = queryRows.iterator();
    while (iter.hasNext()) 
    {
        RepositoryRow row = (RepositoryRow) iter.next();
            
        String ditaTitle 
                = row.getProperties().get("DitaTitle").getStringValue();
        Id docId = row.getProperties().get("Id").getIdValue();
            
        rowCount++;
        System.out.print(" row " + rowCount + ":");
        System.out.print(" Id=" + docId.toString());
        if (ditaTitle != null) 
        {
            System.out.print(" DitaTitle=" + ditaTitle);
        }
        System.out.println();                                    
    }            
    if (rowCount == 0)
    {
        System.out.println("No rows returned for query");
    }
    
}

C# Example

public static void QueryDitaComponent(
        IObjectStore objStore,
        String childVerSeriesId,    // Child document version series id
        String tableName,           // Example: "DitaTopicref" or "DitaConref"
        String propName,            // Example: "DitaId" or "DitaElementId"
        String propValue)           // Property value
{   
    // Show parameters
    Debug.WriteLine("Parameter childVerSeriesId: " + childVerSeriesId);
    Debug.WriteLine("Parameter tableName: " + tableName);
    Debug.WriteLine("Parameter propName: " + propName);
    Debug.WriteLine("Parameter propValue: " + propValue);
    Debug.WriteLine("");

    // Construct SQL object
    // Note: "ChildComponent" could be used in the SQL below instead of
    // "ChildVersionSeries" to query for a specific child docuument. The
    // query below catches all component relationships that bind to any 
    // document within the child version series.
    SearchSQL sqlObject = new SearchSQL();
    sqlObject.SetSelectList("d.id, d.DitaTitle"); 
    sqlObject.SetFromClauseInitialValue("Document", "d", true);
    sqlObject.SetFromClauseAdditionalJoin(JoinOperator.INNER, tableName, "cr", "d.This", JoinComparison.EQUAL, "cr.ParentComponent", false);
    sqlObject.SetWhereClause("cr.ChildVersionSeries = OBJECT(" + childVerSeriesId + ") "
                         + "AND cr." + propName + " = '" + propValue + "'");
    Debug.WriteLine("SQL: " + sqlObject.ToString()); 

    // Execute the query
    SearchScope search = new SearchScope(objStore);
    IRepositoryRowSet queryRows = search.FetchRows(
            sqlObject, 10, null, true);

    // Iterate through the returned rows
    int rowCount = 0;
    foreach (IRepositoryRow row in queryRows)
    {
        String ditaTitle
                = row.Properties["DitaTitle"].ToString();
        String docId = row.Properties["Id"].ToString();
        
        rowCount++;
        Debug.Write(" row " + rowCount + ":");
        Debug.Write(" Id=" + docId);
        if (ditaTitle != null) 
        {
            Debug.Write(" DitaTitle=" + ditaTitle);
        }
        Debug.WriteLine("");                                    
    }            
    if (rowCount == 0)
    {
        Debug.WriteLine("No rows returned for query");
    }

}

Creating a DITARenditionEngineConnection Object

One of the objects needed to publish a DITA document is a connection to a DITA rendition engine. To establish such a connection, follow this sequence of steps (as illustrated in the code example below):

  1. Retrieve or add a publishing configuration.
  2. Create an engine connection object, and set the connection properties.
  3. Save the configuration with the newly created engine connection.

For more information on the DITARenditionEngineConnection object, see DITA Publishing.

Java Example

public static PublishingConfiguration createDitaConnection(
        Domain domain,
        String ditaHome,        // Example: C:/DITA-OT1.4.2.1
        String ditaWorkingDir)  // Example: C:/Temp
{
    // Get default site
    Site site = domain.get_DefaultSite();

    // Get publishing configuration for site
    SubsystemConfigurationList scl 
            = site.get_SubsystemConfigurations();
    PublishingConfiguration pubConfig = getPublishingConfiguration(scl);
    if (pubConfig == null)
    {
        // Add new configuration since one does not already exist 
        pubConfig = addPublishingConfiguration(scl);
    }
            
    // Create new engine connection instance
    DITARenditionEngineConnection newEngineConn 
        = Factory.DITARenditionEngineConnection.createInstance(
          domain, null);
    
    // Set engine connection display name
    SimpleDateFormat timeStamp = new SimpleDateFormat("yyyyMMdd-HHmmss-SSS");
    String displayName = "DREC-" + timeStamp.format(new Date());
    newEngineConn.set_DisplayName(displayName);
    
    // Set engine connection properties
    newEngineConn.set_DITADatabaseTimeout(new Integer(3600));
    newEngineConn.set_DITAHome(ditaHome);
    newEngineConn.set_DITAWorkingDirectory(ditaWorkingDir);
    newEngineConn.set_Site(site);
    
    // Save and associate engine connection with publishing configuration
    newEngineConn.save(RefreshMode.REFRESH);
    pubConfig.set_DITARenditionEngineConnection(newEngineConn);
    System.out.println("DITA engine connection created: " 
                       + newEngineConn.get_Id());   
            
    // Save publishing configuration changes
    site.save(RefreshMode.REFRESH);
    System.out.println("DITA engine connection associated with site: " 
                       + site.get_Id());

    // Re-retrieve publishing configuration to get identifier
    scl = site.get_SubsystemConfigurations();
    pubConfig = getPublishingConfiguration(scl);
    System.out.println(
            "DITA engine connection associated with publishing configuration: "
            + pubConfig.get_Id());      
                
    // Return publishing configuration
    return pubConfig;

}

// Add new publishing configuration
private static PublishingConfiguration addPublishingConfiguration(
        SubsystemConfigurationList scl)
{
    // Create new publishing configuration
    PublishingConfiguration pubConfig 
            = Factory.PublishingConfiguration.createInstance();
    pubConfig.set_DispatcherEnabled(Boolean.TRUE);
    pubConfig.set_DispatcherWaitInterval(new Integer(300));
    pubConfig.set_QueueItemDatabaseTimeout(new Integer(600));
    pubConfig.set_QueueItemMaxDispatchers(new Integer(2));
    pubConfig.set_QueueItemRetryCount(new Integer(3));
    
    // Add publishing configuration
    scl.add(pubConfig);
    return pubConfig;
}

// Get existing publishing configuration (if any)
private static PublishingConfiguration getPublishingConfiguration(
        SubsystemConfigurationList scl)
{
    // Cycle through subsystem configurations
    Iterator iter = scl.iterator();
    while (iter.hasNext() == true)
    {
        // Get next configuration
        SubsystemConfiguration subConfig 
                = (SubsystemConfiguration) iter.next();
        
        // Check if publishing configuration
        if (subConfig instanceof PublishingConfiguration)
        {
            return (PublishingConfiguration) subConfig;
        }
    }
    return null;
    
}

C# Example

public static IPublishingConfiguration CreateDitaConnection(
        IDomain domain,
        String ditaHome,        // Example: C:/DITA-OT1.4.2.1
        String ditaWorkingDir)  // Example: C:/Temp
{
    // Get default site
    ISite site = domain.DefaultSite;

    // Get publishing configuration for site
    ISubsystemConfigurationList scl 
            = site.SubsystemConfigurations;
    IPublishingConfiguration pubConfig = GetPublishingConfiguration(scl);
    if (pubConfig == null)
    {
        // Add new configuration since one does not already exist 
        pubConfig = AddPublishingConfiguration(scl);
    }

    // Create new engine connection instance
    IDITARenditionEngineConnection newEngineConn 
            = Factory.DITARenditionEngineConnection.CreateInstance(
                domain, null);

    // Set engine connection display name
    String displayName = "DREC-" + DateTime.Now.ToString("yyyyMMdd-HHmmss-fff");
    newEngineConn.DisplayName = displayName;

    // Set engine connection properties
    newEngineConn.DITADatabaseTimeout = 3600;
    newEngineConn.DITAHome = ditaHome;
    newEngineConn.DITAWorkingDirectory = ditaWorkingDir;
    newEngineConn.Site = site;

    // Save and associate engine connection with publishing configuration
    newEngineConn.Save(RefreshMode.REFRESH);
    pubConfig.DITARenditionEngineConnection = newEngineConn;
    Debug.WriteLine("DITA engine connection created: " 
                   + newEngineConn.Id); 
        
    // Save publishing configuration changes
    site.Save(RefreshMode.REFRESH);
    Debug.WriteLine("DITA engine connection associated with site: " 
                   + site.Id);

    // Re-retrieve publishing configuration to get identifier
    scl = site.SubsystemConfigurations;
    pubConfig = GetPublishingConfiguration(scl);
    Debug.WriteLine(
            "DITA engine connection associated with publishing configuration: "
            + pubConfig.Id);        
        
    // Return publishing configuration
    return pubConfig;

}

// Add new publishing configuration
private static IPublishingConfiguration AddPublishingConfiguration(
        ISubsystemConfigurationList scl)
{
    // Create new publishing configuration
    IPublishingConfiguration pubConfig
            = Factory.PublishingConfiguration.CreateInstance();
    pubConfig.DispatcherEnabled = true;
    pubConfig.DispatcherWaitInterval = 300;
    pubConfig.QueueItemDatabaseTimeout = 600;
    pubConfig.QueueItemMaxDispatchers = 2;
    pubConfig.QueueItemRetryCount = 3;

    // Add publishing configuration
    scl.Add(pubConfig);
    return pubConfig;
}

// Get existing publishing configuration (if any)
private static IPublishingConfiguration GetPublishingConfiguration(
        ISubsystemConfigurationList scl)
{
    // Cycle through subsystem configurations
    foreach (ISubsystemConfiguration subConfig in scl)
    {           
        // Check if publishing configuration
        if (subConfig is IPublishingConfiguration)
        {
            return (IPublishingConfiguration) subConfig;
        }
    }
    return null;

}

Creating a Publish Style Template for DITA

DITA publishing uses a publish style template (as provided by the IBM FileNet P8 publishing framework) to specify how the rendition engine translates a source document into a different format. A publish style template for DITA publishing uses the following unique transformation options:

Also, the PublishID property on the style template must be set to a publish event handler associated with DITA (for example, PublishRequestDITAPDFHandler).

For more information about the standard publish style template provided by the IBM FileNet P8 publishing framework, see Publishing Concepts and Working with Publish Objects.

Java Example

public static PublishStyleTemplate createDitaStyleTemplate(
        ObjectStore objStore)
{
    // Create instance
    PublishStyleTemplate pubStyleTemplate 
        = Factory.PublishStyleTemplate.createInstance(objStore);
    
    // Set template title
    SimpleDateFormat timeStamp = new SimpleDateFormat("yyyyMMdd-HHmmss-SSS");
    String title = "DITAPublishStyle-" + timeStamp.format(new Date());
    pubStyleTemplate.set_Title(title);

    // Set template formats
    StringList formats = Factory.StringList.createList();
    formats.add("text/xml");
    pubStyleTemplate.set_InputFormats(formats);
    
    // Set template transformation options
    final String TRANS_OPTIONS =
        "<dita-options>"+
            "<ditaval-version-series-id>{DE42374D-B04B-4F47-A62E-CAC9AC9A5719}</ditaval-version-series-id>" +
            "<ditaval-title>Dev. Guide Processing Profile<ditaval-title>"+
            "<trans-type>PDF</trans-type>"+
            "<copy-only>false</copy-only>"+
        "</dita-options>";
    pubStyleTemplate.set_TransformationOptions(TRANS_OPTIONS.getBytes("UTF-16LE"));

    // Set template output format as PDF
    pubStyleTemplate.set_OutputFormat("application/pdf");
    
    // Set the event handler
    pubStyleTemplate.set_ProviderID("PublishRequestDITAPDFHandler");
    
    // Save template
    pubStyleTemplate.save(RefreshMode.REFRESH);
    System.out.println("Publish style template created: " 
                       + pubStyleTemplate.get_Id());
    return pubStyleTemplate;
    
}

C# Example

public static IPublishStyleTemplate CreateDitaStyleTemplate(
        IObjectStore objStore)
{
    // Create instance
    IPublishStyleTemplate pubStyleTemplate 
            = Factory.PublishStyleTemplate.CreateInstance(objStore);

    // Set template title
    String title = "DITAPublishStyle-" 
                 + DateTime.Now.ToString("yyyyMMdd-HHmmss-fff");
    pubStyleTemplate.Title = title;

    // Set template formats
    IStringList formats = Factory.StringList.CreateList();
    formats.Add("text/xml");
    pubStyleTemplate.InputFormats = formats;

    // Set template transformation options
    String TRANS_OPTIONS =
        "<dita-options>"+
            "<ditaval-version-series-id></ditaval-version-series-id>" +
            "<trans-type>pdf</trans-type>"+
            "<copy-only>false</copy-only>"+
        "</dita-options>";
    System.Text.ASCIIEncoding encoding 
            = new System.Text.ASCIIEncoding();
    pubStyleTemplate.TransformationOptions 
            = encoding.GetBytes(TRANS_OPTIONS);

    // Set template output format as PDF
    pubStyleTemplate.OutputFormat = "application/pdf";

    // Set the event handler
    pubStyleTemplate.ProviderID = "PublishRequestDITAPDFHandler";

    // Save template
    pubStyleTemplate.Save(RefreshMode.REFRESH);
    Debug.WriteLine("Publish style template created: " 
                    + pubStyleTemplate.Id);
    return pubStyleTemplate;

}

Creating a Publish Template for DITA

DITA publishing uses a publish template (as provided by the IBM FileNet P8 publishing framework) to specify options for a publishing request. A publish template for DITA publishing must specify a publish style template. If the publish template has no associated style template, document publication causes a copy of the source document (DITA map), without its referenced components, to be created in the object store output folder.

For more information about the standard publish template provided by the IBM FileNet P8 publishing framework, see Publishing Concepts and Working with Publish Objects.

Java Example

public static PublishTemplate createDitaTemplate(
        ObjectStore objStore,
        String ditaOutputFolder,    // Example: /Publication
        boolean copyOnly)           // Set to false for DITA Publishing
{
    // Create instance
    PublishTemplate pubTemplate 
            = Factory.PublishTemplate.createInstance(objStore);

    // Set template title
    SimpleDateFormat timeStamp = new SimpleDateFormat("yyyyMMdd-HHmmss-SSS");       
    String title = "DITAPublish-" + timeStamp.format(new Date());
    pubTemplate.getProperties().putValue("DocumentTitle", title);
    
    // Create content transfer element for template content
    final String PUBLISH_TEMPLATE_CONTENT 
            = buildTemplateContent(ditaOutputFolder);
    ByteArrayInputStream inputStream 
            = new ByteArrayInputStream(PUBLISH_TEMPLATE_CONTENT.getBytes());
    ContentTransfer contentElement 
            = Factory.ContentTransfer.createInstance();
    contentElement.setCaptureSource(inputStream);
    contentElement.set_RetrievalName("DitaPublishTemplate.xml");
    contentElement.set_ContentType("application/x-filenet-publishtemplate");
    
    // Add content transfer element
    ContentElementList cel = Factory.ContentElement.createList();
    cel.add(contentElement);
    pubTemplate.set_ContentElements(cel);
    
    // Set style template (calls create-style-template snippet)
    if (copyOnly == false)
    {
        PublishStyleTemplate pubStyleTemplate 
            = SnippetsAdvancedDocManagement.createStyleTemplate(objStore);
        pubTemplate.set_StyleTemplate(pubStyleTemplate);
    }

    // Checkin and save
    // Need to checkin because publishing only takes 
    // the current major version on the publish template
    pubTemplate.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, 
                        CheckinType.MAJOR_VERSION);
    pubTemplate.save(RefreshMode.REFRESH);
    System.out.println("Publish template created: " 
                       + pubTemplate.get_Id());
    return pubTemplate;     
   
}

// Build template content 
private static String buildTemplateContent(
        String ditaOutputFolder)    // Example: /Publication            
{
    final String VALUE_ISSOURCEDEPENDENT = "true";

    // publish template content
    final String PUBLISH_TEMPLATE_CONTENT =
        "<?xml version=\"1.0\" ?>" +
        "<publishtemplatecontent>" +
        "<version>2.0.1</version>" +
        "<newinstructions>" +
            "<issourcedependent>" + VALUE_ISSOURCEDEPENDENT + "</issourcedependent>" +
            "<outputfoldername>" + ditaOutputFolder + "</outputfoldername>" +
            "<applyproperties>" +
                "<classdescriptionname>Document</classdescriptionname>" +
                "<properties>" +
                "<property>" +
                    "<name>DocumentTitle</name>" +
                    "<value>MyNewDITAPubTitle</value>" +
                "</property>" +
                "</properties>" +
            "</applyproperties>" +
            "<applysecurity>" +
                "<from>default</from>" + // apply security from class definition
            "</applysecurity>" +
        "</newinstructions>" +
        "<republishinstructions>" +
            "<versionablerepublishtype>versionandkeep</versionablerepublishtype>" +
            "<nonversionablerepublishtype>addandkeep</nonversionablerepublishtype>" +
            "<applypropertiesfrom>destination</applypropertiesfrom>" +
            "<applysecurityfrom>destination</applysecurityfrom>" +
        "</republishinstructions>" +
        "</publishtemplatecontent>";
    
    // Return string
    return PUBLISH_TEMPLATE_CONTENT;
}

C# Example

public static IPublishTemplate CreateDitaTemplate(
        IObjectStore objStore,
        String ditaHome,            // Example: C:/DITA-OT1.4.2.1           
        String ditaOutputFolder,    // Example: /Publication            
        Boolean copyOnly)           // Set to false for DITA Publishing
{
    // Create instance
    IPublishTemplate pubTemplate 
            = Factory.PublishTemplate.CreateInstance(objStore);

    // Set template title
    String title = "DITAPublish-" 
                 + DateTime.Now.ToString("yyyyMMdd-HHmmss-fff");
    pubTemplate.Properties["DocumentTitle"] = title;

    // Create content transfer element for template content
    String PUBLISH_TEMPLATE_CONTENT 
            = buildTemplateContent(ditaOutputFolder);
    System.Text.ASCIIEncoding encoding 
            = new System.Text.ASCIIEncoding();
    System.IO.Stream inputStream 
            = new MemoryStream(encoding.GetBytes(PUBLISH_TEMPLATE_CONTENT));
    IContentTransfer contentElement 
            = Factory.ContentTransfer.CreateInstance();
    contentElement.SetCaptureSource(inputStream);
    contentElement.RetrievalName = "DitaPublishTemplate.xml";
    contentElement.ContentType = "application/x-filenet-publishtemplate";

    // Add content transfer element
    IContentElementList cel = Factory.ContentElement.CreateList();
    cel.Add(contentElement);
    pubTemplate.ContentElements = cel;

    // Set style template (calls create-style-template snippet)
    if (copyOnly == false)
    {
        IPublishStyleTemplate pubStyleTemplate
            = SnippetsAdvancedDocManagement.CreateStyleTemplate(
                    objStore);
        pubTemplate.StyleTemplate = pubStyleTemplate;
    }

    // Checkin and save
    // Need to checkin because publishing only takes 
    // the current major version on the publish template
    pubTemplate.Checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, 
                        CheckinType.MAJOR_VERSION);
    pubTemplate.Save(RefreshMode.REFRESH);
    Debug.WriteLine("Publish template created: " 
                    + pubTemplate.Id);
    return pubTemplate;     

}

// Build template content 
private static String buildTemplateContent(
        String ditaOutputFolder)    // Example: /Publication            
{
    String VALUE_ISSOURCEDEPENDENT = "true";

    // publish template content
    String PUBLISH_TEMPLATE_CONTENT =
        "<?xml version=\"1.0\" ?>" +
        "<publishtemplatecontent>" +
            "<version>2.0.1</version>" +
            "<newinstructions>" +
                "<issourcedependent>" + VALUE_ISSOURCEDEPENDENT + "</issourcedependent>" +
                "<outputfoldername>" + ditaOutputFolder + "</outputfoldername>" +
                "<applyproperties>" +
                    "<classdescriptionname>Document</classdescriptionname>" +
                    "<properties>" +
                        "<property>" +
                            "<name>DocumentTitle</name>" +
                            "<value>MyNewDITAPubTitle</value>" +
                        "</property>" +
                    "</properties>" +
                "</applyproperties>" +
                "<applysecurity>" +
                    "<from>default</from>" + // apply security from class definition
                "</applysecurity>" +
            "</newinstructions>" +
            "<republishinstructions>" +
                "<versionablerepublishtype>versionandkeep</versionablerepublishtype>" +
                "<nonversionablerepublishtype>addandkeep</nonversionablerepublishtype>" +
                "<applypropertiesfrom>destination</applypropertiesfrom>" +
                "<applysecurityfrom>destination</applysecurityfrom>" +
            "</republishinstructions>" +
        "</publishtemplatecontent>";

    // Return string
    return PUBLISH_TEMPLATE_CONTENT;
}

Publishing a DITA Project

The code example below publishes a DITA document. To accomplish this, it calls the methods shown in the previous examples to create a DITA rendition engine connection and a DITA publish template. (The publish template method also creates a publish style template when the value of the copy-only parameter is false.) The example sets the title of the published document using the publish <publicationname> option. Other publish options allow you to override options set in the publish template; for more information, see Publish XML Options.

Notes:

Java Example

public static void publishDitaDocument(
        ObjectStore objStore,
        Document sourceDitaDoc, 
        String ditaHome,            // Example: C:/DITA-OT1.4.2.1
        String ditaWorkingDir,      // Example: C:/Temp
        String ditaOutputFolder,    // Example: /Publication 
        boolean copyOnly)           // Set to true if publishing = copying
        throws Exception
{
    // Show parameters
    System.out.println("Parameter copyOnly: " + copyOnly);
    System.out.println("");
    
    // Make sure the publishing configuration has a DITA engine connection
    // (calls create-DITA-Connection snippet)
    SnippetsAdvancedDocManagement.createDitaConnection(
            objStore.get_Domain(), ditaHome, ditaWorkingDir);
    
    // Get publish template (calls create-template snippet)
    PublishTemplate pubTemplate 
        = SnippetsAdvancedDocManagement.createTemplate(
                objStore, ditaHome, ditaOutputFolder, copyOnly);
    
    // Build publish options
    SimpleDateFormat timeStamp = new SimpleDateFormat("yyyyMMdd-HHmmss-SSS");
    String title = "DITAdocument-" + timeStamp.format(new Date());
    String pubOptions = new String(
            "<publishoptions><publicationname>"
            + title 
            + "</publicationname></publishoptions>");

    // Publish document
    PublishRequest pubRequest 
            = sourceDitaDoc.publish(pubTemplate, pubOptions);
    pubRequest.save(RefreshMode.REFRESH);
    System.out.println("Submitted request to publish document with title '" 
                        + title + "'");
    
}

C# Example

public static void PublishDitaDocument(
        IObjectStore objStore,
        IDocument sourceDitaDoc,    
        String ditaHome,            // Example: C:/DITA-OT1.4.2.1
        String ditaWorkingDir,      // Example: C:/Temp
        String ditaOutputFolder,    // Example: /Publication 
        Boolean copyOnly)           // Set to true if publishing = copying
{
    // Show parameters
    Debug.WriteLine("Parameter copyOnly: " + copyOnly);
    Debug.WriteLine("");
    
    // Make sure the publishing configuration has a DITA engine connection
    // (calls create-DITA-Connection snippet)
    SnippetsAdvancedDocManagement.CreateDitaConnection(
            objStore.Domain, ditaHome, ditaWorkingDir);

    // Get publish template (calls create-template snippet)
    IPublishTemplate pubTemplate 
            = SnippetsAdvancedDocManagement.CreateTemplate(
                    objStore, ditaHome, ditaOutputFolder, copyOnly);

    // Build publish options
    String title = "DITADocument="
                 + DateTime.Now.ToString("yyyyMMdd-HHmmss-fff");
    String pubOptions = 
            "<publishoptions><publicationname>"
            + title
            + "</publicationname></publishoptions>";

    // Publish document
    IPublishRequest pubRequest 
            = sourceDitaDoc.Publish(pubTemplate, pubOptions);
    pubRequest.Save(RefreshMode.REFRESH);
    Debug.WriteLine("Submitted request to publish " +
                    "document with title '" + title + "'");

}