This topic provides the following DITA publishing-related tasks and code examples:
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.
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).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).
DitaLqref
class to DitaBaseref
.
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
DitaMsg
class to DitaBaseref
.
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);
DitaBase
class.
// 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));
DitaBase
class.
// 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));
// 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));
Note: You must perform this procedure before you create any Document
instances that use the
updated properties.
private static final int MAX_DEFAULT_METADATA_STRING_SIZE = 80;
If you plan to use a customized DITA classifier, perform the following procedures.
Note: This setting means that the DITA classifier will only be invoked on documents with a mime type of application/dita+xml.
To statically define the DITA Open Toolkit invocation environment:
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%
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; }
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"); } }
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):
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; }
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; }
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; }
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 + "'"); }