XML Productivity Features
Transcription
XML Productivity Features
XML Productivity Features Technical Note #10044 Version InDesign CS Feb 2004 ADOBE SYSTEMS INCORPORATED Corporate Headquarters 345 Park Avenue San Jose, CA 95110-2704 (408) 536-6000 Copyright 2004 Adobe Systems Incorporated. All rights reserved. The information in this document is furnished for informational use only, is subject to change without notice, and should not be construed as a commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or liability for any errors or inaccuracies that may appear in this document. The software described in this document is furnished under license and may only be used or copied in accordance with the terms of such license. Adobe, Adobe After Effects, Adobe InDesign, Adobe PhotoDeluxe, Adobe Premiere, Adobe Photoshop, Adobe Illustrator, Adobe Type Manager, ATM and PostScript are trademarks of Adobe Systems Incorporated that may be registered in certain jurisdictions. Macintosh and Apple are registered trademarks, and Mac OS is a trademark of Apple Computer, Inc. Microsoft, Windows, Windows 95, Windows 98, and Windows NT are registered trademarks of Microsoft Corporation. All other products or name brands are trademarks of their respective holders.. Rev # Date Author Comments 0.1 Nov 2003 Ian Paterson New outline for CS features; re-write of the 2.0 tech-note. 0.2 Dec 2003 Ian Paterson Refactored to new structure based on pattern as follows; feature-description, design, usecases per feature area 0.3 Jan 2003 Ian Paterson Tidied up prior to review and re-factored slightly. 0.4 Jan 2004 Ian Paterson Rolled in Rodney Cook’s review comments 0.5 Jan 2004 Ian Paterson Integrated review comments from Ken Sadahiro. Contents Chapter XML Productivity Features . . . . . . . . . . . . . . . . . . . . . . . 7 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Terminology and definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Programming and the application object model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Modelling the domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Features In InDesign CS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Character styles mapped to tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Support for XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Validation against DTD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Support for table headers and footers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Support for comments and processing instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Customising the SAX parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Walkthrough: importing XML into a template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Importing graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Importing text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Key design concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Logical structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Key associations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Document element and root element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Importing and exporting XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Suites and utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Import and export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Feature description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Importing XML data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Exporting XML data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Importing a table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Exporting a table to XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Tags and the tag-list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Feature description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Loading tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Saving tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3 Contents Creating, updating and deleting tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Mappings between tags and run-styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Feature description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Creating and modifying the mapping from tag to run-style . . . . . . . . . . . . . . . . . . . . . . 49 Creating and modifying the mapping from run-style to tag . . . . . . . . . . . . . . . . . . . . . . 50 Applying a mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Changing logical structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Feature description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Creating, updating and deleting elements and attributes . . . . . . . . . . . . . . . . . . . . . . . 60 Tagging text and graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 DTD and validation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Feature description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Associate DTD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Validate against DTD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Processing instructions and comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Feature description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Adding comments and processing instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 User interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Feature description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Visibility of the structure-view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Appearance of the structure-view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 XSL support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Feature description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Transforming imported XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Walkthrough: transforming imported XML with XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 Extension points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Custom suite for the structure-view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 XSL Enabler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Custom SAX Content handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Custom tag service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Custom SAX entity resolver. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Frequently asked questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 What is the difference between logical structure and the native document model? . . . . . . . 78 4 Feb 2004 XML Productivity Features Contents How do I make a selection in the structure view? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 How do I create, update or delete elements in the logical structure? . . . . . . . . . . . . . . . . 79 How can I read in some arbitrary XML content? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 How do I validate an XML document from within the applications? . . . . . . . . . . . . . . . . . 80 How do I change the XML import options?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Summary and conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Native document model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Backing store. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 Root backing store and notification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Low-level command notification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Entities supported . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Assets from XSLT example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 XML Productivity Features Feb 2004 5 Contents 6 Feb 2004 XML Productivity Features XML Productivity Features Overview XML Productivity Features Overview This document provides an overview of the design of the XML features available in InDesign CS and describes how to work with the XML-related API as a client of the API. It also introduces some XML-related extension points that allow you to customize the behaviour of the applications. The feature highlights for this release include support for validation against a document type definition (DTD) and support for applying an XSL style sheet during import to transform between XML grammars. Terminology and definitions This section defines terms used within this document alone. Some fundamental terms used in the API (e.g. boss class, add-in) are defined here to ensure that the meaning of these terms for the reader of this document is consistent the one intended by the author. • add-in; an interface that decorates an existing boss class. It is defined in the resource language ODFRez (Object Definition Format resource language). • API; InDesign CS Application Programming Interface. • API documentation; refers to the API documentation in the SDK in a browseable format (Windows Compiled Help/ HTML) generated from doc++ style comments in the source code and information from FR files and the object model. • application; InDesign CS unless otherwise defined. • applications; InDesign CS and InCopy CS unless otherwise defined. • backing store; a container that manages the persistent boss objects that represent elements in the logical structure of a document, represented in the API by kSBOSPageBoss. Each InDesign CS document contains a root backing store, and each user-accessible story (kTextStoryBoss) has its own backing store that contains the elements representing the logical structure within the story. • boss class; a boss class is a compound type expression at the core of the application object model. The term “boss” was orginally used to signify an entity that managed or “bossed” a collection of interfaces. Boss classes represent objects in the application domain and provide their behaviour; for instance, a publication (kDocBoss), a spread (kSpreadBoss), a page (kPageBoss). A boss class can extend or subclass another boss class, but the inheritance model allows for only a single superclass. Like an add-in, this type must defined in the resource language ODFRez. XML Productivity Features 7 XML Productivity Features Terminology and definitions • boss object; an instance of a boss class. • comment, XML; a comment valid within an XML document, represented in the API by kXMLCommentBoss. XML comments are defined in the XML 1.0 specification [http://www.w3.org/TR/REC-xml] as follows: “Comments may appear anywhere in a document outside other markup; in addition, they may appear within the document type declaration at places allowed by the grammar. They are not part of the document's character data...” • content handler; responsible for reading XML content from an input stream. There is an extension point described in the section “Custom SAX Content handler” on page 75 which specifies how to customize handling of XML content to enable reading your own custom data from a stream. • content item; an object in the native document model that can be associated with an element in the logical structure. Examples are placeholder items (kPlaceHolderItemBoss), images (kImageItem) and stories (kTextStoryBoss); these have the interface IXMLReferenceData which stores the association with an element. A textrange within a story (kTextStoryBoss) is also a content item, since it can be tagged. • document element; element in the logical structure associated with the root node of the native document model (kDocBoss), represented by kXMLDocumentBoss. A singleton instance of this class is present in the document’s root backing store. You should be aware that this is defined differently to “document element” in the XML 1.0 specification [http://www.w3.org/TR/REC-xml], which is equivalent to root element in the InDesign CS XML API. • document type declaration (DTD) defines the grammar for a class of documents, represented by kXMLDTDBoss. The XML 1.0 specification [http://www.w3.org/TR/REC-xml] defines a DTD as follows: ] “The XML document type declaration contains or points to markup declarations that provide a grammar for a class of documents. This grammar is known as a document type definition, or DTD. The document type declaration can point to an external subset (a special kind of external entity) containing markup declarations, or can contain the markup declarations directly in an internal subset, or can do both. The DTD for a document consists of both subsets taken together.” • element; a node in the logical structure of an XML document, represented in the API by boss classes that expose the interface IIDXMLElement. The XML 1.0 specification [http://www.w3.org/TR/REC-xml] defines an element as follows: “Each XML document contains one or more elements, the boundaries of which are either delimited by start-tags and end-tags, or, for empty elements, by an empty-element tag. Each element has a type, identified by name, sometimes called its “generic identifier” (GI), and may have a set of attribute specifications. Each attribute specification has a name and a value.” • entity; these are containers for content in an XML document. There is an extension point that lets you customize the behaviour of the application when dealing with external entities; see “Custom SAX entity resolver” on page 77. The XML 1.0 specification defines entities as follows: An XML document may consist of one or many storage units. These are called entities; they all have content and are all (except for the document entity and the external DTD subset) identified by entity name. 8 XML Productivity Features Terminology and definitions • generic identifier; name of an element in an XML document, which corresponds to the tag-name • graphic frame; a placeholder for graphic content. In the API, boss classes (e.g. kSplineItemBoss) that represent the behaviour of graphic frames aggregate an IGraphicFrameData interface. • interface; in the domain of the API, refers to an abstract C++ class that is a descendant of the API class IPMUnknown; interfaces are aggregated on boss classes to make their capabilities accessible to client code. • logical structure; the logical structure of an InDesign CS document consists of a tree of elements. The elements are represented by boss classes that have the interface IIDXMLElement. The logical structure can also contain a DTD element, processing instructions and comments. • ODFRez; a resource language. The OpenDoc Framework Resource Language that allows cross-platform resources to be defined for plug-ins. Boss classes and add-ins must be defined in ODFRez, along with data statements defining menu elements, user interface widgets and so on. • persistence; this is defined by Webster’s as a “property of a programming language where created objects and variables continue to exist and retain their values between runs of the program” . Application documents are lightweight databases that maintain the state of persistent boss objects which represent domain objects. See the chapter entitled Persistence architecture for a more detailed discussion of this key topic. • persistent interface; strictly speaking, a “persistent implementation of an interface”; the implementation must in its code use the macro CREATE_PERSIST_PMINTERFACE to define that it implements a persistent interface, and provide a ReadWrite method where its state is serialized. • persistent boss object; a boss object that saves its state across sessions. Persistent boss classes, at least UID-based ones, aggregate the interface IPMPersist; instances of these classes read and write their state to application databases (e.g. documents) through persistent interfaces. • placed content; elements in the backing store which are associated with document content. There is a small visual indicator in the structure-view that indicates whether an element is associated with a placed content item. In terms of the model, this means that the IIDXMLElement::GetContentItem returns something other than kInvalidUID. • placeholder; this is a target for XML import. It can be a graphic frame that has a tag applied to identify it as a target for content from an XML import. If a text container is marked-up, the placeholder is the story (kTextStoryBoss) rather than the containing frame. • processing instruction; (PIs) these allow documents to contain instructions for applications. They take the form <?application-name ... ?>. The XML 1.0 specification notes that: PIs are not part of the document's character data, but must be passed through to the application. The PI begins with a target (PITarget) used to identify the application to which the instruction is directed. XML Productivity Features 9 XML Productivity Features Terminology and definitions 10 • root backing store; the instance of the backing store present by default in every document. It stores the document element (kXMLDocumentBoss), any DTD element (kXMLDTDBoss) and other elements including the root element (instance of kTextXMLElementBoss) and its immediate children. • root element; element in the logical structure appears as the root element in the structureview. It is represented by an instance of the class kTextXMLElementBoss. By default, it has a tag-name Root. • SBOS; small boss object store. The backing store (kSBOSPageBoss) uses this storage mechanism; it is an example of container-managed persistence (CMP). • text-based marker; marked-up text in a story is enclosed by zero-width characters present in the text model. These cannot be deleted individually, only in matched pairs. The character inserted is represented in the text model by kTextChar_ZeroSpaceNoBreak [see the SDK header file named public/includes/TextChar.h]. • tag-name; associated with the name of an element, that is, its generic identifier in terms used in the XML specification. A tag is represented in the API by kXMLTagBoss, which also stores the colour as it appears in the Tags panel in the user interface. • tag-collection, tag-list; the set of tags that can participate in the logical structure of a document. Represented in the API by IXMLTagList, stored in a workspace (e.g. kDocWorkspaceBoss). • tagged content item; an instance of a content item that has been subject to tagging. In terms of the model, this means that IXMLReferenceData::GetReference would return a valid XMLReference. • tagging; the process of applying mark-up to content items. Note that it has no connection with “tagged text”, a non-XML based format that the applications use to import and export styled text. Content items that can be tagged aggregate the interface IXMLReferenceData. • unplaced content; items can exist in the logical structure which are associated with text or reference images, but are not present in the document layout and are not linked to items in the native document model. • XML; eXtensible Mark-up Language is used for defining mark-up languages; it is a metalanguage rather than a language. Specification for current version defined as W3C Recommendation [see http://www.w3.org/TR/REC-xml]. • XML data; content that is defined in an XML based language • XML template; an InDesign CS document that has tagged place-holders into which XML data can be flowed. • XSLT; eXtensible Stylesheet Language: Transformations. Specification for current version defined as W3C Recommendation [see http://www.w3.org/TR/xslt]. XML Productivity Features Introduction Introduction This document provides information about the XML-related features of the applications that are relevant to the needs of systems integrators and plug-in developers in general. There is also some detailed documentation on the XML features for end-users in the HTML-based help for InDesign CS and InCopy CS, which should be consulted if you are unfamiliar with these features. This document has the following goals: • Sketch the application features supporting XML. • Explain how logical structure of InDesign CS documents is represented, in terms of the classes and interfaces, their responsibilities and their associations. • Identify use cases involving XML. • Explain how to work with the InDesign CS XML API as a client. • Identify some XML-related extension points for InDesign CS. XML itself is a specification that enables mark-up languages to be defined. An XML-language is created for a particular purpose, with domain-specific semantics; for instance, DocBook is an XML-based language for documenting software systems [http://www.oasisopen.org/docbook/xml/]. News Industry Text Format or NITF [http://www.nitf.org/] is an example of an XML-based language for representing newspaper content. There are several reasons why XML workflows might be used in print publishing: 1. If content to be published is already available in an XML-based language, e.g. in NITF or NewsML [http://www.newsml.org], that has already been customized for the publishing domain. 2. To maintain independence of content from both layout and styling information. This goes beyond the separation of content and layout that is possible in a workflow with InCopy CS and InDesign CS being used to edit copy and layout respectively. 3. To support re-purposing of content for different media from a single source; for instance, you might want to publish newspaper content to multiple media such as print, Web, Adobe PDF and/or Mobile SVG. 4. To capitalize on the large number of toolkits and standardized APIs that make it relatively easy to manipulate XML documents. 5. To take advantage of databases that are XML-aware. Programming and the application object model Rather than viewing InDesign CS programming as something exotic, we take the view that it is not radically different from the object-oriented programming (OOP) model in OOP languages XML Productivity Features 11 XML Productivity Features Programming and the application object model such as Java, C# or SmallTalk. The InDesign CS programming model is sufficiently different from Microsoft COM that comparison with the latter is not very illuminating. The design of the application is expressed in terms of boss classes that model domain objects and the relationships between them. The view taken here is that analysis in terms of boss classes provides the best way to understand the model. Interfaces represent aspects of boss classes; interfaces do not typically represent domain objects. We try to focus attention on boss classes to make explicit the design of the underlying data model. In keeping with object-oriented methodology, we model the application as a community of agents (boss objects) sending each other messages. We identify boss classes involved in modelling the domain, their responsibilities and their collaborations with other boss classes. This is the perspective taken when modelling a system using CRC cards [see Beck et al, http://c2.com/doc/oopsla89/paper.html]. Since we are using object-oriented language to understand the model, we need to be explicit about what we mean in the InDesign CS API by an object; we need to think in terms of boss objects, instances of boss classes. We can consider their interfaces as a means of scoping messages that are sent to boss objects. The InDesign CS object model (ObjectModelLib component) supports the type-system based on boss classes; it also manages loading and unloading of plug-ins. The object model is responsible for creating and destroying boss objects. It is also responsible for tracking the plugins that are installed (IPlugInList) and maintaining metaclass information (IClassInfo) about boss classes delivered by installed plug-ins. 12 XML Productivity Features Programming and the application object model FIGURE 1 Key parts of the object model «library» Object Model Lib Plug-in List Responsible for maintaining a list of all the currently installed plug-ins. See IPlugInList. Responsible for storing metadata about boss classes known to the object model. Class Dictionary Interface Registry Responsible for maintaining information needed to create and destroy the implementations (instances of C++ classes) that make up boss objects. See IClassInfo. Not public API. When you define boss classes and add-ins in an FR file of your plug-in using the ODFRez resource language, the information in these type expressions ends up in the object model, in its class dictionary. See the figure “Key parts of the object model” on page 13 for the main components of the object model. The object model maintains meta-information about boss classes that let you discover (for instance) what boss class a given interface belongs to by writing code like this: InterfacePtr<IControllingUnknown> boss(someInterface, UseDefaultIID()); // We know that IControllingUnknown is present by default on every boss class ClassID classID = boss->GetClass(); InterfacePtr <IObjectModel> objectModel(gSession, UseDefaultIID()); TRACE("Boss class name is %s. ", objectModel->GetIDName(classID)); Modelling the domain In the API, domain objects are modelled by boss classes, classes defined in an exotic resource language named ODFRez. These classes are meaningful within the application’s object model. If you are familiar with the object-oriented metaphor of a program as a community of interacting agents sending each other messages, then you will be comfortable with the view that you program InDesign CS by sending messages to boss objects. The set of messages a given boss object understands depends on the interfaces that it exposes or aggregates. An interface is an abstract C++ classes that is a descendant of the API class IPMUnknown. For instance, you might send a message IIDXMLElement::FindChild to an object of class kTextXMLElementBoss when working in the logical structure. The class kTextXMLElementBoss extends the abstract boss class named kXMLElementBoss, which provides the core behaviour for elements in the logical structure. XML Productivity Features 13 XML Productivity Features Programming and the application object model You extend the application by delivering new boss classes in your plug-ins or decorating existing ones with new interfaces via add-ins. More strictly, you can extend the application if you deliver building blocks in your plug-in. Boss classes and add-ins are the basis for these building blocks, which are software patterns that fit into the applications’ extension points. For instance, an action component is a building block that lets you add a menu item and be notified when your menu item is clicked on. We describe some that are specific to XML in the section entitled “Extension points” on page 73. The native document model and the (XML) logical structure are defined in terms of boss classes. To represent the design of the native document model and the XML subsystem, we adopt a UML-based notation with some domain-specific stereotypes and conventions. A boss class consists of a set of interfaces and something to manage this collection; that is, boss (i.e. manage) the interfaces. The managing entity is represented in the API by IControllingUnknown, an interface present on every boss class by default. FIGURE 2 Boss class in UML notation IControllingUnknown «boss class» kXMLTagBoss IXMLTag IPersistUIDData The figure entitled “Boss class in UML notation” on page 14 shows an example of a boss class in this notation. Although IControllingUnknown is shown in this diagram, by convention, it is omitted from the others. Other points about the notation are use of <<boss class>> as a stereotype for a class. We do not attempt to display all the interfaces on a particular boss class, only those relevant to the model being depicted. A boss class defines the behaviour for instances of that class; the behaviour depends on the semantics of interfaces that the boss class aggregates, and how they have been implemented. If we write that a particular interface on a boss class has a responsibility for something, this is shorthand for “the implementation class associated with a particular interface on a given boss class” has a responsibility for something. Since this is an unwieldy expression, we prefer to speak in terms of the responsibilities of interfaces on a particular boss class. For instance, we write: “The interface IXMLTagList is responsible for storing a collection of tags in a workspace...” even though IXMLTagList is an abstract C++ class. What we mean by the statement is that the implementation of the interface IXMLTagList is responsible for storing the collection of tags, but we are contracting it so that we can write more compactly “The interface ... is responsible for ...”, rather than having to obfuscate the meaning by introducing “implementation of ”. We can now write that interfaces are responsible for storing something or doing something. For instance, one particularly significant piece of information that they can store is a reference to another object; for instance, one object can store a UID that refers to another object. This is how the majority of the associations that we describe in sections such as “Key associations” on page 24 are persisted. 14 XML Productivity Features Features In InDesign CS Features In InDesign CS Character styles mapped to tags The applications now support mapping both character styles and paragraph styles to tags, and vice versa; InDesign version 2.0 supported only mapping paragraph styles. See the use case entitled “Applying a mapping” on page 50. Support for XSLT The application now supports transformation of the incoming XML during import by applying an XSL style sheet. This feature is intended to transform between XML grammars, for instance, to allow data from data-sources in different XML languages to be imported into a single XML template. This feature is concerned with mapping between XML grammars, not styling the content on import. See the section entitled “XSL support” on page 68. Validation against DTD A document type declaration (DTD) can be associated with the logical structure of an InDesign CS document. An InDesign CS document can be validated against the grammar the DTD represents. The application reports any validation errors that occurred to the end-user along with suggested corrections. See the section “DTD and validation” on page 61. At the time of writing, the InDesign CS API does not support validating the logical structure of a document against a grammar expressed in an XML schema [http://www.w3.org/TR/xmlschema-0/]. Support for table headers and footers InDesign CS now supports header rows and footer rows in tables; the XML support for importing and exporting tables has been extended to support this and this information can be round-tripped in XML files. See the use cases “Importing a table” on page 39 and “Exporting a table to XML” on page 40. Support for comments and processing instructions InDesign CS now supports adding XML comments and processing instructions to the logical structure of a document. See the section entitled “Processing instructions and comments” on page 64. Customising the SAX parser There are extension points that are new for InDesign CS that let you customise the behaviour of the XML parser. These include the ability to handle custom content in an XML document being imported; see “Custom SAX Content handler” on page 75. XML Productivity Features 15 XML Productivity Features Walkthrough: importing XML into a template Walkthrough: importing XML into a template The intent of this section is to provide a walk-through of some of the XML features, before considering the XML API in detail. We examine a basic but non-trivial workflow, where images and structured text are imported into an InDesign CS document that has placeholders for graphics and/or text-based content. Whilst these are end-user features that we are going to walk through, you would automate some of this in a workflow for a publishing system. The walk-through gives some context for the discussion of the design that we introduce later. Importing graphics In this section, we work through a minimal example where we import a pair of images into an XML template, in this case, based on a new document to which you will add one tag and two graphic frames. FIGURE 3 XML specifying images to import <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Root> <Image href="file://images/ColObj-1.gif"></Image> <Image href="file://images/ColObj-2.gif"></Image> </Root> 16 1. Save the XML in the figure “XML specifying images to import” on page 16 to a file called “image-example.xml” in the “examplefiles” folder in <sdk>/source/sdksamples/xdocbookworkflow. 2. Create a new document. Create a new tag called Image using the Tags panel (Window > Tags). Make sure that you have the Structure view visible (View > Structure > Show structure). Make sure that View > Structure > Show tagged frames is enabled also. 3. Create two graphic frames with the Rectangle tool. Apply the Image tag to each by selecting the graphic frame, and then clicking in the Tags panel. XML Productivity Features Walkthrough: importing XML into a template FIGURE 4 Tagged placeholders for images 4. Import the XML from “image-example.xml” into your document. You should see that the images have been placed in the graphic frames you tagged. 5. Try altering the ordering of the Image elements in the structure-view. This does not change the layout, because we are not changing the content item (contained in a layout object) each element in the logical structure is associated with. Importing text The example described in the shows “Importing graphics” on page 16 how graphic content can be imported by references in the imported XML. Another important use case is importing textual content with existing logical structure. We can model the content of a publication as a set of articles, broken down into sections. One option is to use an existing XML-based language that supported this content model. Another option would be to define our own XML-based language, as shown in the worked example“Transforming imported XML” on page 69. For this example we use the DocBook model, or at least a very small subset of its large vocabulary. Consider the DocBook XML in the figure entitled “Minimal XML file to be imported” on page 17. Note that this is an instance of the book document type, which defines a set of articles. FIGURE 5 Minimal XML file to be imported <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <book> <article> <section> <title>First</title> <para>Hello world</para> </section> </article> <article> <section> <title>Second</title> <para>Hello world again</para> </section> </article> XML Productivity Features 17 XML Productivity Features Walkthrough: importing XML into a template </book> This XML file is to be imported into a template; the template chosen for the illustration was based on one delivered in the CS SDK with small changes. 18 1. Save the XML in “Minimal XML file to be imported” on page 17to a file called “textexample.xml” 2. Open the template file in the “examplefiles” folder that can be found in <sdk>/source/sdksamples/xdocbookworkflow; this template is named templatewin.indt or templatemac.indt, depending on your platform. Delete the text frames on page 1, 2 and on the master pages. This is because we are going to create separate text frames tagged “article”. This template by default has a story running through the master text frames which is tagged “article”, so we have to delete the master text frames and the individual text frames based on the master text frames. 3. Save this untitled document as “xml-text-example.indd”. 4. Add the tag “book” to the document “xml-text-example.indd”. You can do this either by creating it through the Tags panel (Window > Tags) or by loading tags from the file “text-example.xml”. 5. You have to add the “book” tag at this point because you are going to change the tag on the root element in the structure-view before the XML data is imported. Now change the tag on the root element from “article” to “book”. Select the root element in the structureview and use the context-sensitive menu that appears on a right mouse click (Windows) or control-click (Macintosh) to change the tag. 6. Create two new text frames, and tag each with the tag “article”. This has the effect of tagging the story running through the frame; be aware that the user-interface suggests that the text frame is being tagged. 7. Make sure that you have the Structure view visible (View > Structure > Show structure). Make sure that View > Structure > Show tagged frames is enabled also. You should see that there are two “article” elements that appear as placed content; in this case, each “article” element has an association with a tagged story. 8. Import the XML from “text-example.xml”. XML Productivity Features Walkthrough: importing XML into a template 9. You should be able to see two articles on the page, and the structure view should represent the logical structure within each article; that is, a section, a title and paragraph as its children. 10. Choose the option to view text snippets from the Structure pop-out menu on the Structure pane. Expand the elements of the structure and you should see something similar to that below. 11. Try changing the order of the “title” and “para” elements in the structure-view by dragging-and-dropping within the structure-view window (e.g. move the “para” element above the “title” element). You will see the layout change, because the content items associated with the elements are story ranges within a given story and re-arranging the logical structure now affects the story order. Recall how re-ordering the “Image” elements in the previous example didn’t affect the layout. Structure that is within a story does affect the layout when it changes. 12. Place the text tool in one of the frames and bring up the story editor (Edit > Edit in story editor). You should see a representation of the tags in the story editor view. XML Productivity Features 19 XML Productivity Features Key design concepts FIGURE 6 Story editor view of story with XML mark-up Key design concepts This section introduces key design concepts that are needed to understand the design of the XML subsystem. Other concepts that relate to the XML subsystem but that are less central to understanding its design are dealt with in the Appendix (see “Appendix” on page 81); for instance, the native document model (“Native document model” on page 81) and backing store (“Backing store” on page 84) . Logical structure The logical structure of an InDesign CS document is a tree of elements representing logical relationships between elements. XML data can be imported to create or modify the logical structure of a document; see “Importing XML” on page 35. Existing content items can be tagged to modify logical structure; this is described in the section entitled “Changing logical structure by tagging content” on page 51. FIGURE 7 Tagged content item K4EXT8-,%LEMENT"OSS K3PLINE)TEM"OSS K8-,4AG"OSS K0LACE(OLDER)TEM"OSS The native document model specifies how end-user documents are represented by InDesign CS. End-users work with spreads, pages, layout objects such as graphic frames, guides and so on, and these are represented in the native document model. The logical structure of a document consists of a tree of elements, which may have associations with content items in the native document model. 20 XML Productivity Features Key design concepts The logical structure of an InDesign CS document can be exported as an XML document that contains text, mark-up and references to images; see the section “Exporting XML” on page 36. The logical structure of a document depends on: 1. the tag collection, a list of tag objects (kXMLTagBoss) that belong to a workspace (e.g. kDocWorkspaceBoss), 2. the backing store (see “Backing store” on page 84), responsible for managing elements and their links to content items in the document model, as well as links to tag objects. The figure entitled “Tagged content item” on page 20 shows a minimal document, with a single graphic frame (kSplineItemBoss) with a dependent placeholder item (kPlaceHolderItemBoss). The placeholder item tagged with “Image”, stored in a tag object (kXMLTagBoss). Elements (represented by boss classes with the interface IIDXMLElement) are rendered in the structure-view, which is a view of a document’s logical structure. FIGURE 8 Native document model and logical structure Native document model contentTagged Logical structure tagsUsed Tags and the tag-list Backing stores When document content is marked-up or tagged, elements (represented by boss objects that expose the interface IIDXMLElement) are created within the document’s logical structure and contained in its backing store; see “Backing store” on page 84. Elements can also be created by importing XML; see “Importing XML” on page 35. Tagging creates associations between content items and elements in the logical structure. Tagging also creates associations between objects representing tags (kXMLTagBoss) and the elements in the logical structure. This is shown in the high-level diagram entitled “Native document model and logical structure” on page 21 and described in more depth in the section entitled “Key associations” on page 24. XML Productivity Features 21 XML Productivity Features Key design concepts After tagging a content item: 1. the backing store contains objects representing elements in the logical structure, which refer to content items in the document model, 2. the objects representing the elements in the logical structure are associated with tag objects, which are contained in the tag-list stored in a workspace, 3. content items in the document model have associations with objects representing elements in the logical structure. Importing XML into an InDesign CS document creates new elements in the logical structure. This can result in content being automatically placed within the layout, or maintained as unplaced content within the document’s logical structure, depending on whether the document has tagged placeholder page items. 22 XML Productivity Features Key design concepts FIGURE 9 Instance diagram showing example of logical structure «boss class» document element : kXMLDocumentBoss IIDXMLElement::GetNthChild «boss class» book (root) : kTextXMLElementBoss No tag is associated with the document element, and it doesn't appear in the structure-view IIDXMLElement::GetTagUID tag : kXMLTagBoss IIDXMLElement::GetNthChild IIDXMLElement::GetNthChild «boss class» article : kTextXMLElementBoss «boss class» article : kTextXMLElementBoss IIDXMLElement::GetNthChild IIDXMLElement::GetNthChild Boss objects representing an element in the logical structure can have a link to an instance of kXMLTagBoss that stores the tag name Only one is shown in the interests of clarity in this diagram. «boss class» section : kTextXMLElementBoss «boss class» section : kTextXMLElementBoss How this logical structure would be rendered in the structure-view window The logical structure of an InDesign CS document consists of a tree of elements; each element in the tree is represented by a boss object with the interface IIDXMLElement and has a link to a boss object representing its tag (kXMLTagBoss). See the figure entitled “Instance diagram showing example of logical structure” on page 23 for an instance of a logical structure. Note how each element in the tree has an association linking it with a boss object that represents its tag (kXMLTagBoss). The logical structure is easier to work with than the native document model; see “Native document model” on page 81. You may need different interfaces to navigate through the XML Productivity Features 23 XML Productivity Features Key design concepts native document model, depending on your starting point and where you want to get to; for instance, to navigate from the root node (kDocBoss) to a graphic frame on a spread would require use of methods on the interfaces ISpreadList, ISpread and IHierarchy. Navigation within the logical structure is easier; you can use a single interface. To navigate through the logical structure, you can use methods on the interface IIDXMLElement, regardless of your starting point and destination. Key associations The XML subsystem establishes associations between elements in the logical structure and content in the native document model, at least for placed content or tagged placeholders. Elements are also associated with tags that store their tag-names. The elements in the logical structure are held in a backing store, and tagged content items can be associated with the story (kTextStoryBoss) that owns the backing store; see “Backing store” on page 84. There are several key associations maintained by the XML subsystem that we consider in detail in this section: 1. content items in the native document model are associated with elements in the logical structure. The association is maintained via the interface IXMLReferenceData and the helper class XMLReference; see “Association from native document model to logical structure in UML” on page 25. 2. Elements in the logical structure are associated with content items in the native document model. The association is maintained by the interface IIDXMLElement; see “Association from logical structure to native document model in UML” on page 26. 3. Elements in the logical structure are associated with tags. The association is maintained by the interface IIDXMLElement; see “Association from logical structure to tag in UML” on page 27. 4. Content items in the native document model are associated with the story (kTextStoryBoss) that owns the backing store (kSBOSPageBoss). The association is maintained by the interface IIDXMLElement; see “Associations involving content item and backing store” on page 28. The associations are shown in a structural diagram for a tagged placeholder in the figure entitled “Tagged content item” on page 28. Since understanding these associations is the key to understanding the XML model, each association is considered in the context of the example introduced in the figure “Tagged content item” on page 20. 24 XML Productivity Features Key design concepts FIGURE 10 Association from native document model to logical structure in context K4EXT8-,%LEMENT"OSS K3PLINE)TEM"OSS K8-,4AG"OSS K0LACE(OLDER)TEM"OSS Content items (with an IXMLReferenceData interface) can have an association with an element in the logical structure. For instance, a tagged graphic frame that is a placeholder for an image is represented an object of class kPlaceHolderItemBoss, with a parent of class kSplineItemBoss; see figure “Association from native document model to logical structure in context” on page 25. When the frame is tagged, an association is set up with an element in the logical structure, of class kTextXMLElementBoss; see “Association from native document model to logical structure in UML” on page 25. FIGURE 11 «boss class» kPlaceHolderItemBoss Association from native document model to logical structure in UML IXMLReferenceData 1 0..1 IIDXMLElement «boss class» kTextXMLElementBoss «helper class» XMLReference Instantiate() Boss classes that aggregate the interface IXMLReferenceData represent content items that can be tagged; see “Native document model and XML-related interfaces” on page 83. In other words, the interface IXMLReferenceData lets content items be linked to elements in the logical structure, since it stores a reference to an element in the logical structure. If an item is not tagged, then this reference will be invalid. An illustration of this association is shown in “Association from native document model to logical structure in UML” on page 25. XML Productivity Features 25 XML Productivity Features Key design concepts Along with content items, the class representing the root of the native document model (kDocBoss) aggregates the interface IXMLReferenceData, which has the responsibility for maintaining an association with the document element (kXMLDocumentBoss). Note that the class kXMLDocumentBoss itself has two IXMLReferenceData interfaces with different interface identifiers; one is responsible for maintaining an association with a DTD element, if there is one (kXMLDTDBoss). See the structural diagram “Structural diagram involving document element” on page 33. FIGURE 12 Association from logical structure to native document model in context K4EXT8-,%LEMENT"OSS K3PLINE)TEM"OSS K8-,4AG"OSS K0LACE(OLDER)TEM"OSS Elements in the logical structure have an association with one or zero content items. If they represent placed content or a tagged placeholder, then they are associated with one content item. If they are not placed (or they are structural elements) then they are associated with zero content items. The example shown in the figure “Association from logical structure to native document model in context” on page 26 is an example where the element represents a tagged placeholder. The UML for this association is shown in the figure “Association from logical structure to native document model in UML” on page 26 FIGURE 13 Association from logical structure to native document model in UML IIDXMLElement «boss class» kTextXMLElementBoss 1 IIDXMLElement::GetContentItem «boss class» kPlaceHolderItemBoss 0..1 The interface IIDXMLElement lets an element in the logical structure be associated with a content item. It stores a reference to a content item, which is invalid if the element is not 26 XML Productivity Features Key design concepts associated with placed content or a tagged placeholder. An illustration of this association is shown in the figure entitled “Association from logical structure to native document model in UML” on page 26. Note that any content item (exposing the interface IXMLReferenceData) could be substituted for kPlaceHolderItemBoss in this diagram. FIGURE 14 Association from logical structure to tag in context K4EXT8-,%LEMENT"OSS K3PLINE)TEM"OSS K8-,4AG"OSS K0LACE(OLDER)TEM"OSS Elements in the logical structure are associated with tags, that store the element’s tag-name. This is shown in the context of the example of a tagged placeholder in the figure “Association from logical structure to tag in context” on page 27. FIGURE 15 Association from logical structure to tag in UML 1 «boss class» kTextXMLElementBoss IIDXMLElement IIDXMLElement::GetTagUID 0..1 «boss class» kXMLTagBoss IXMLTag The interface IIDXMLElement lets an element in the logical structure be associated with a tag; it stores a reference to an tag object (kXMLTagBoss) which is populated with a tag whose name corresponds to the element’s tag-name. This is shown in the figure entitled “Association from logical structure to tag in UML” on page 27. The interface IXMLReferenceData can be used to obtain an XMLReference object; this lets you acquire a reference to the object representing an element (e.g. kTextXMLElementBoss), as well as to the object that owns the backing store, which will be an instance of kTextStoryBoss. XML Productivity Features 27 XML Productivity Features Key design concepts FIGURE 16 «boss class» kPlaceHolderItemBoss Associations involving content item and backing store IXMLReferenceData 1 0..1 «boss class» kTextStoryBoss «helper class» XMLReference GetUID() owns 1 1 «boss class» kSBOSPageBoss Represents a backing store, which manages a collection of elements (with the interface IIDXMLElement) We have considered the associations of elements with content items and with tags. To complete the picture, we note that the elements are held in backing stores (see “Backing store” on page 84), and that there is a further association between the content item and the story (kTextStoryBoss) that manages the backing store. This is shown in the structural diagram entitled “Associations involving content item and backing store” on page 28. Note that any content item (exposing the interface IXMLReferenceData) could be substituted for kPlaceHolderItemBoss in this diagram. FIGURE 17 Tagged content item K4EXT8-,%LEMENT"OSS K3PLINE)TEM"OSS K8-,4AG"OSS K0LACE(OLDER)TEM"OSS We will now introduce a more detailed structural diagram for a tagged placeholder with these associations and other key classes; see figure “Tagged content item” on page 28. 28 XML Productivity Features Key design concepts FIGURE 18 Backing store and tagged page item Each story has an associated backing-store that manages a collection of elements (with interface IIDXMLElement) representing the logical structure within the story. Graphic frame tagged as placeholder «boss class» kSplineItemBoss Use IXMLReferenceData to get XMLReference IHierarchy::GetChildUID «boss class» kPlaceHolderItemBoss The root backing store contains the elements that are not tied to a specific user-accessible story. «helper class» XMLReference GetUID() «boss class» kTextStoryBoss IXMLReferenceData 1 1 Association from native document model to logical structure 0..1 Backing store 1 «boss class» kSBOSPageBoss «helper class» XMLReference Instantiate() owns 1 stores 0..1 This class is a container for the objects representing elements in the logical structure 1..* 1 IIDXMLElement::GetContentItem «boss class» kTextXMLElementBoss IIDXMLElement 1 IIDXMLElement::GetTagUID Association from logical structure to native document model 1 «boss class» kXMLTagBoss Anything that aggregates IIDXMLElement can occur in the root backing store. Other backing stores contain boss objects that aggregate IIDXMLElement except for the document element (kXMLDocumentBoss) and the DTD element (kXMLDTDBoss) 1..* IXMLTagList::GetTag 1 «boss class» kDocWorkspaceBoss The diagram in the figure entitled “Backing store and tagged page item” on page 29 shows the classes and associations involved when a graphic frame is tagged as a placeholder for an image, which includes some of the associations already introduced. XML Productivity Features 29 XML Productivity Features Key design concepts If an image is placed, then the boss class kPlaceHolderItemBoss is replaced in the model by the boss class representing the image (e.g. kImageItem, kEPSItem, kPlacedPDFItemBoss and so on. To find out more about the data model for a tagged story or text range, see “Tagging text” on page 57. To find out more about the relationships that exist. in an empty document, see “Document element and root element” on page 32 The object diagram entitled “Instance diagram for a tagged content item” on page 31 is based on the example “Tagged content item” on page 28; you should also consult the structural diagram entitled “Backing store and tagged page item” on page 29, which this instance diagram is a realisation of. The instance diagram makes explicit the links that exist between the objects representing elements in the logical structure and (a) content items and (b) tags. You should be aware that although the instance diagram shows properties of the boss objects, this is just a device to make the notation more compact. In practice the properties would be accessed through an interface, and stored by a persistent implementation of an interface. For instance, the properties such as the tag UID and the content item UID are accessed through the interface IIDXMLElement, and stored by its persistent implementation kXMLElementImpl. 30 XML Productivity Features Key design concepts FIGURE 19 Instance diagram for a tagged content item «boss class» XML-story : kTextStoryBoss UID = 92 Instance of a story that is present in every document, a non-user-accessible story. The UID is specific to this example; you should not expect it always to be 92. owns «boss class» placeholder item : kPlaceHolderItemBoss UID = 138 Class that represents the backing store. Although its architecture is opaque to client code, the interfaces like IIDXMLElement indicate how the elements are stored within the backing store «boss class» root backing store : kSBOSPageBoss stores hasContent stores stores «boss class» document element : kXMLDocumentBoss LSID = 1 BaseUID = 92 «boss class» root element : kTextXMLElementBoss LSID = 2 BaseUID = 92 ContentItemUID = 0 TagUID = 107 hasTag Elements present by default in a newly created document. Note the LSID (logical store identifier) is equivalent to a record number within the backing store. The BaseUID refers to the kTextStoryBoss that owns the backing store. «boss class» Root tag : kXMLTagBoss UID = 107 «boss class» image 1 : kTextXMLElementBoss LSID = 3 BaseUID = 92 ContentItemUID = 138 TagUID = 137 hasTag «boss class» Image tag : kXMLTagBoss UID = 137 An element we created that is linked to a placeholder item for an image. This is specific to the example. Since we have linked it to a content item in the native document model, the ContentItemUID is now something other than zero (kInvalidUID). XML Productivity Features 31 XML Productivity Features Key design concepts Document element and root element This section examines the role of two key objects present in the logical structure of any InDesign CS document and explains how they fit into the design. These objects are the document element and root element. The document element (represented by kXMLDocumentBoss) is associated with the root node in the document model (kDocBoss). The document element is responsible for managing document-level information, such as any associated DTD and document-level comments or processing instructions. This is not equivalent to the “root, or document element” of the XML specification [http://www.w3.org/TR/REC-xml] because it does not have an associated tag and is not represented when XML is exported from InDesign CS. This element is not shown in the structure-view. The root element (an instance of kTextXMLElementBoss) is the root of the element hierarchy in the logical structure. By default it has the tag “Root”. This is equivalent to the “root element” in the XML specification. 32 XML Productivity Features Key design concepts FIGURE 20 Structural diagram involving document element The root element is represented by kTextXMLElementBoss. In an empty document, the root element has the tag-name "Root". «boss class» kTextXMLElementBoss IIDXMLElement «helper class» XMLReference Instantiate() The helper class XMLReference is used to navigate the association. It is obtained from IXMLReferenceData and lets one acquire a reference to a boss object that supports IIDXMLElement. «helper class» XMLReference Instantiate() «boss class» kDocBoss IXMLReferenceData The interface IXMLReferenceData on kXMLDocumentBoss stores a reference to the root element of the document, "Root" by default «boss class» kXMLDocumentBoss IXMLReferenceData IIDXMLElement IXMLReferenceData (IID_IXMLDTDXMLREFERENCEDATA) There is a second IXMLReferenceData interface on kXMLDocumentBoss with an exotic interface identifier that stores a reference to the DTD element The class kXMLDocumentBoss is unique in that it has both IIDXMLElement and IXMLReferenceData interfaces. The instance of the document element (kXMLDocumentBoss) is held in the root backing store. «boss class» kXMLDTDBoss IIDXMLElement «helper class» XMLReference Instantiate() If you are familiar with the XML specification, then you should be cautious because “document element” has a different meaning within the InDesign CS API to the XML specification, which treats document element and root element as the same thing. In the InDesign CS API, document element and root element are two distinct concepts. As shown in the figure “Structural diagram involving document element” on page 33, the document element (kXMLDocumentBoss) is associated with the root node of the native document model (kDocBoss). The interface IXMLReferenceData on kDocBoss stores a reference to the document element (kXMLDocumentBoss). The logical structure is held in the backing store of an InDesign CS document; see the section entitled “Backing store” on page 84. The document element and root element are held in the root backing store, along with other immediate children of the root element; see “Root backing store and notification” on page 86. XML Productivity Features 33 XML Productivity Features Key design concepts Importing and exporting XML When XML data is imported, the XML subsystem creates elements in the logical structure (see “Logical structure” on page 20). XML content can be imported into an XML template, which has place-holder items with tags that match element names in the XML data to be imported. An example is shown in the section “Walkthrough: importing XML into a template” on page 16. 1. If there are tagged content items in the layout that match the element tag-names in the imported XML, then content is automatically placed on import; that is, images would be placed in the graphic frames containing the placeholder (kPlaceHolderItemBoss) or flowed into the story (kTextStoryBoss) that was tagged. 2. If there are no matching tagged items in the layout, then elements are created in the logical structure, but their content is held in the backing store without being placed; see “Backing store” on page 84. Import of XML does not use the standard import service architecture, but rather a specialised XML parser service (kXMLParserServiceBoss). Export of XML uses the standard export service architecture (see IExportProvider). See the section entitled “Import and export” on page 35 for more detail on the import and export of XML. Suites and utilities XML suites A suite is a API that lets you program at a level of abstraction above the model, dealing only in terms of an abstract selection. You should consult the tech-note on Selection architecture (#10006) for more detail on what is meant by a suite. A selection can be created either by an end-user, or sometimes programmatically, so a suite interface may be used to automate tasks even if an end-user is not able to make a selection. There are some suite interfaces that can be used to program the XML features, which represent a fairly high level of abstraction over the XML subsystem. These suites are recommended as a first point of call if you are programming the XML features. 34 • IXMLNodeSelectionSuite can be used to make a programmatic selection in the structureview window. • IXMLStructureSuite can be used when there is a selection in the structure-view window. It lets you change the logical structure of a document at the node selected in the structure-view tree. If you are writing client code that will involve the end-user making active selections, this is one mechanism to modify the logical structure tree. The methods on this suite interface delegate to the command facades. • IXMLTagSuite can be used to apply tags to a selection, such as a text range or graphic frame(s). It can also be used for other purposes such as adding a processing comment to the document’s logical structure; see the use case “Adding comments and processing instructions” on page 66. XML Productivity Features Import and export You can extend the application by writing a custom suite that would be available when there is a selection in the structure-view window. See the section on “Extension points” on page 73 and the tech-note on Selection for more assistance. Command facades and utilities There are many command-related boss classes named kXML<whatever>CmdBoss but in most cases you do not need to process these low-level commands, as there are facades you should use that encapsulate parameterizing and processing these commands. Interfaces such as IXMLUtils, IXMLElementCommands, IXMLMappingCommands, IXMLTagCommands and IXMLAttributeCommands are instances of command facades. These encapsulate processing of almost all of the commands required by plug-in code; you will also find that most of the data interfaces in the XMedia are not required by client code, since they relate to commands that are processed by one of these wrapper interfaces. These interfaces are aggregated on kUtilsBoss; there is a smart pointer class Utils that makes it straighforward to acquire and invoke methods on these interface. You can invoke their methods by writing code that follows the pattern: Utils<IXMLElementCommands>()->MethodName(...) You should always look first at the IXMLUtils or IXML<whaver>Commands interfaces, to see if there is a method that serves your purpose on one of these interfaces to avoid processing low-level commands. There are perhaps some low-level commands that you may need to process, where there are gaps in the facade. The use cases indicate whether a low-level command would need to be processed to execute the use case. Import and export Feature description Importing XML The application supports import of XML encoded as: • UTF-8 [http://www.ietf.org/rfc/rfc2279.txt], • UTF-16 [http://www.ietf.org/rfc/rfc2781.txt], • Shift-JIS, [http://www.w3.org/TR/2000/NOTE-japanese-xml-20000414/], a two-byte format for Japanese. The workflow within InDesign CS is a little different to other structured editors, such as FrameMaker + XML, where there is a single flow of text and the logical structure of the document is determined by a single XML. With InDesign CS, you can import several XML files into the logical structure of the document. You can also export a subset of the document logical structure into an XML file There are two main workflows: XML Productivity Features 35 XML Productivity Features Import and export 1. Importing the XML into the backing store, and then manually placing onto the layout to set up the associations between elements in the logical structure and document object. 2. Creating an InDesign CS document as an XML-template that contains placeholders; these placeholders are tagged with names of the elements in the XML data to import. The contents of the XML file can be flowed into the placeholders by the application as it is imported. The order that the elements appear in the logical structure determines how the content is flowed into the tagged placeholders. To import content, there are several options that are available on the Import XML options dialog: 1. “Replace Content” replaces existing tagged layout objects from where the root of the XML file matches the tag of the selected element. Select this option if you are using a template with tagged placeholders. 2. “Append Content” can be used to create new elements at the end of the document logical structure. 3. “Import into Selected Element” can be used to import XML content into the element selected in the Structure pane. If this option is not selected, imported elements will appear under the root element. Exporting XML You can export the logical structure of an InDesign CS document as an XML document; the export takes place in document order [http://www.w3.org/TR/xpath, Section 5], meaning that the logical structure of the InDesign CS document and exported XML are the same. By default, an empty InDesign CS document has a single element “Root” in its logical structure. If a new InDesign CS document is created and exported as XML, then a single element <Root/> is written to the output file; see “Structure of empty document and XML exported” on page 36. FIGURE 21 Structure of empty document and XML exported "[POYHUVLRQ HQFRGLQJ 87)VWDQGDORQH \HV"! 5RRW ! There are a couple of points to note about the relation between XML exported from InDesign CS and the logical structure: 1. 36 XML content can be exported from a document even if it is not associated with placed content in the document. XML exported is based on the logical structure, irrespective of whether the elements are associated with content in the document. XML Productivity Features Import and export 2. The order in which the elements appear in the output XML is based entirely on the logical structure, and has no direct relation with the document native model. The exception to this is the case of a story with mark-up, where the order of the elements in the logical structure within the sub-tree corresponding to the story corresponds to the story reading order. By default, InDesign CS does not support exporting a selection within the layout window and will export the entire document; however, note that you can export a selection of tags within the Tags panel. You can write additional code to allow an end-user to export a layout selection. Note that a selection within the structure-view window can be exported. Design Unlike other forms of import, e.g. EPS (import provider kEPSPlaceProviderBoss) or PDF (import provider kPDFPlaceProviderBoss) say, importing XML does not use the standard import provider (IImportProvider) architecture. Rather, it relies on an XML parser service, represented by the class kXMLParserServiceBoss; this has the ServiceID of kXMLParserService and a service interface of ISAXServices. The behaviour of XML parser (kXMLParserServiceBoss) is controlled by ISAXParserOptions; see InCopyDocUtils.cpp (<sdk>/source/sdksamples/incopyfileactions) for an instance of this being used. Parsing errors are stored in the interface IXMLServicesError exposed by the parser boss class. The import process depends on SAX content handler services (see ISAXContentHandler). The default top-level content handler for importing XML is kSAXDocumentHandlerBoss; see the description of content handlers in the section entitled “Custom SAX Content handler” on page 75. The XML parser service also looks for all other SAX content handler services and registers them, to enable them to handle content during parsing if they choose. Controlling the parser becomes particularly relevant when you implement your own custom SAX content handler and use it as the top-level handler; see “Custom SAX Content handler” on page 75. XML Productivity Features 37 XML Productivity Features Import and export FIGURE 22 Interfaces storing options for import and export Options that are stored in a specific document «boss class» kDocWorkspaceBoss IXMLExportSessionOptions «boss class» kWorkspaceBoss IXMLImportOptions IXMLExportOptions IXMLImportOptions IXMLExportOptions Session-specific options and options inherited by new documents An XML file can be exported when content objects have been tagged; this can be based on a selection from the logical structure via the structure view or the logical structure of the entire document. See the snippet named SnpImportXML.cpp in the folder <sdk>/source/sdksamples/codesnippets for an example of using the import service and controlling the XML import options. Alternatively, you can make a programmatic selection in the structure-view prior to the import to determine where the imported XML should be located in the logical structure. See the FAQ entitled “How do I make a selection in the structure view?” on page 78. XML export takes place using the standard export service architecture. See the snippet named SnpExportXML.cpp in the folder <sdk>/source/sdksamples/codesnippets for an example of using the XML export service. Importing XML data There is a command named kImportXMLFileCmdBoss which can be processed to import an XML file. It has data interfaces as follows: 38 • an interface IImportFileCmdData, specifying the target database (document) for the import and the path to the file to import, • an interface IStylesheetData, specifying an XSLT style sheet (if any) to apply on import; see the section “Support for XSLT” on page 15, • an interface IXMLReferenceData used to specify the parent element in the existing logical structure. XML Productivity Features Import and export The behaviour of the command to import XML depends on the import options (see IXMLImportOptions); see the diagram “Interfaces storing options for import and export” on page 38. The options can be changed through processing a command of class kChangeXMLImportOptionsCmdBoss. There is a snippet named SnpImportXML.cpp that shows in more detail an instance of processing this command, and see also XDocBookWorkflow code for another example of programmatic import of XML. The relevant code can be found in the folder named <sdk>/source/sdksamples/xdocbookworkflow. Importing XML via this command (kImportXMLFileCmdBoss) means that you are limited to the default entity resolution of the application. If you have more advanced requirements and you want to provide your own entity resolver for use during the import process, then you need to write a custom import XML command of your own. See the section entitled “Custom SAX entity resolver” on page 77. Exporting XML data Exporting XML goes through the standard export provider architecture, so you can obtain an XML export service from the service registry (IK2ServiceRegistry) knowing the ServiceID identifying an export service (kExportProviderService) and a ClassID for the XML export service (kXMLExportProviderBoss). You can find code showing XML export in the SDK code-snippet named SnpExportXML.cpp (<sdk>/source/sdksamples/codesnippets) and the SDK sample named XDocBookWorkflow (<sdk>/source/sdksamples/xdocbookworkflow) Importing a table A table defined in an XML file can be imported into InDesign CS.This can be imported in at least two ways; 1. As part of an XML document that they are importing, in which case the table elements are silently consumed on import. 2. As a stand-alone XML file that contains the specification for a single table. If the root element of this XML file is a table element, then it is possible to import this into a selected node in the logical structure. If the table is to be imported unplaced, i.e. directly into the backing store without there being a selected element in the logical structure, the “table” element has to be wrapped in some other element (e.g. “Story”), since the “table” element and its sub-tree of dependents is stripped on import. One key point is that once InDesign CS has imported the table, it is no longer a “structured” table and cannot be manipulated through the structure-view, or programmatically via manipulating the logical structure. The SDK sample named XDocBookWorkflow (located in the folder <sdk>/source/sdksamples/xdocbookworkflow) shows one mechanism to work with tables that are defined in a XML-based language that uses a different content model for tables to the HTML-based content model. Ideally, use a custom SAX content handler to strip out the table- XML Productivity Features 39 XML Productivity Features Import and export related elements on import (see “Extension points” on page 73) rather than directly deleting them from the logical structure, as XDocBookWorkflow does. Exporting a table to XML The precondition for exporting a table from InDesign CS is that it is contained in a tagged story. If it is not, then the default behaviour is to ignore on export. If it is contained in a tagged story, then it will be exported to a content model that is based on that for HTML tables; see [http://www.w3.org/TR/REC-html40/struct/tables.html] and the RFC document from the IETF at [http://www.ietf.org/rfc/rfc1942.txt]. The main difference is that the table content is qualified by an Adobe namespace, referred to by “aid” or “InDesign”, which can be found defined as: xmlns:aid="http://ns.adobe.com/AdobeInDesign/3.0/" xmlns:InDesign="adobe:ns:InDesign/" For instance, exporting a table that contains two columns, a header row, two body rows and footer row results in the XML fragment shown in the figure entitled “Exported table” on page 41. 40 XML Productivity Features Tags and the tag-list FIGURE 23 Exported table - <aid:table xmlns:aid="http://ns.adobe.com/AdobeInDesign/3.0/"> - <aid:thead> - <aid:tr> <aid:td>Header cell 1</aid:td> <aid:td>Header cell2</aid:td> </aid:tr> </aid:thead> - <aid:tbody> - <aid:tr> <aid:td>Body cell1 content</aid:td> <aid:td>Body cell2 content</aid:td> </aid:tr> - <aid:tr> <aid:td>Body cell 3 content</aid:td> <aid:td>Body cell 4 content</aid:td> </aid:tr> </aid:tbody> - <aid:tfoot> - <aid:tr> <aid:td>Footer cell 1</aid:td> <aid:td>Footer cell 2</aid:td> </aid:tr> </aid:tfoot> </aid:table> Tags and the tag-list Feature description End-users can load a set of tags through executing the menu item on the pop-out menu of the Tags panel to populate the tag-list; see the figure “Tags panel and structure view” on page 42. Tags can be loaded from several datasources: 1. An InDesign CS tag-file, an XML document containing only tag-specific information. 2. Any XML document that is an instance of the document type that is being worked with. 3. By associating a DTD with the document. Doing this means that the DTD is parsed for element tag-names and tags are created correspondingly. Note that at the time of writing, elements that are defined within entities are ignored. FIGURE 24 Sample tag-list <?xml version="1.0" encoding="UTF-16" standalone="yes"?> <article colorindex="4"> <articleinfo colorindex="6"/> ... (other elements omitted) <ulink colorindex="19"/> XML Productivity Features 41 XML Productivity Features Tags and the tag-list </article> It is also possible to specify the colour of the tag using RGB co-ordinates, which is used for any tags defined with a “Custom” colour. The co-ordinates are encoded using the scheme described in the section “Hex encoded numbers” in the InCopy story format specification (see tech-note #10083). For instance, a single tag with a custom colour that is the RGB co-ordinate (0,0,255) appears as: <link rgb="0 0,0 0,3ff00000 0"/> In addition, there is an extension point that lets you customize what tags are created when an XML document is being parsed; for instance, you might want to ignore some elements in the input XML. This extension point is described in the section “Custom tag service” on page 76 FIGURE 25 Tags panel and structure view An end-user can create a new tag by making a gesture involving the Tags panel, which adds an entry to the tag list. Creating a new tag means that it is now available to mark-up content or tag placeholder graphic frames for content. An end-user can delete a tag with a gesture involving the Tags panel. An end-user can export the tag-list by executing a pop-out menu item on the Tags panel. Design The tags that can be applied to mark-up content items in a document are stored in the tag-list (IXMLTagList), a collection of tag objects (kXMLTagBoss) that is stored in a workspace. 42 XML Productivity Features Tags and the tag-list FIGURE 26 Structural model for tags and tag-list The tag-list is a collection of kXMLTagBoss objects stored in a workspace object «boss class» kDocWorkspaceBoss IXMLTagList ISubject «boss class» kWorkspaceBoss 1 IXMLTagList ISubject 1 IXMLTagList::GetTag IXMLTagList::GetTag Multiplicity is at least one at the tag end, because every document by default has the tag Root. Multiplicity is zero at the kXMLTagBoss end because the session workspace by default has no tags 1..* 0..* «boss class» kXMLTagBoss The methods needed to create, update properties of and delete tags are found in IXMLTagCommands on the class kUtilsBoss IXMLTag IPMPersist Tags are UID-based persistent objects, hence the interface IPMPersist The name and color for the UI are stored in IXMLTag. The boss class named kXMLTagBoss that represents an individual entry in a tag-list. The signature interface of this boss class is IXMLTag; this stores properties such as the name and the colour in the user-interface. The tag-list is represented by IXMLTagList, which is: • aggregated on the session workspace (kWorkspaceBoss); tags that would be present in any newly created document, • aggregated on the document workspace (kDocWorkspaceBoss); tags that are present in a given document. Tagging relationships are represented by associations between classes representing elements in the logical structure and those representing tags. For instance, if a graphic frame is tagged for use as a placeholder, then an association is created between the placeholder boss object (an instance of the class kPlaceHolderItemBoss) and an instance of the class kTextXMLElementBoss. An association is created between an element in the logical structure XML Productivity Features 43 XML Productivity Features Tags and the tag-list (kTextXMLElementBoss) and an instance of kXMLTagBoss to represent the tagging. See the figure “Structural diagram for tagging placeholder item” on page 56 for this association. Loading tags Loading tags can be performed using the command facade IXMLTagCommands, present on the boss class kUtilsBoss. Loading tags means changing the tag-list (IXMLTagList) stored in the active workspace: 1. if there is no document, the target for the change is the session workspace (kWorkspaceBoss) 2. if a document is open, the target for the change is the document workspace (kDocWorkspaceBoss) See the figure “Loading a new tag list” on page 44 for code illustrating this. FIGURE 27 Loading a new tag list // Let db be target database (e.g. document into which tags are to be loaded), // and tagsSysFile be path to tag file to load InterfacePtr<IXMLTagList> tagList( Utils<IXMLUtils>()->QueryXMLTagList(db)); ErrorCode err = Utils<IXMLTagCommands>()-> LoadTagList(::GetUIDRef(tagList), tagsSysFile); See the snippet <sdk>/source/sdksamples/codesnippets/SnpPerformXMLTags.cpp for an example of this code being used in a richer context. Tag lists (see IXMLTagList) are held in the document workspace (kDocWorkspaceBoss). A list of tags loaded into a document, making them available to mark-up content in that document. The contents of the tag list should be manipulated using IXMLTagCommands, not changed through direct modification of the tag-list, otherwise you can corrupt the document. See the section entitled “Saving tags” on page 44 for the format of the tag list XML file. Under the hood, the low-level command kLoadTagListCmdBoss is processed whenever a taglist is imported. See the table “Low-level command notification details” on page 87 if you want to find out more about how to observe this being processed by the application. Saving tags The tag list (IXMLTagList) is exported as an XML document, with elements specifying the name and the colour index for each of the tags. The root element in the logical structure has the same name as the root-element in the exported tag-list and names of the other elements match those in the tag-list. A fragment of a tag-list is shown in the figure “Sample tag-list” on page 41. To save a tag-list programmatically, you can use IXMLTagCommands. FIGURE 28 // // // // 44 Saving a tag-list Assume that db refers to the document database from which tags are exported, and sysFile is the path to the file to save. SDKFileSaveChooser (in SDK) is useful for selecting a file in this context XML Productivity Features Tags and the tag-list InterfacePtr<IXMLTagList> tagList(Utils<IXMLUtils>()->QueryXMLTagList(db)); ErrorCode err = Utils<IXMLTagCommands>()->SaveTagList(::GetUIDRef(tagList), sysFile); See the snippet <sdk>/source/sdksamples/codesnippets/SnpPerformXMLTags.cpp for a more complete example of implementing this use case. Creating, updating and deleting tags Tags are represented in the API by kXMLTagBoss, with the key interface IXMLTag. Tag objects (instances of the class kXMLTagBoss) are managed by the IXMLTagList interface on kDocWorkspaceBoss or kWorkspaceBoss. Since IXMLTagList is part of the model, changes to IXMLTagList must go through a low-level command. The facade interface IXMLTagCommands encapsulates the low-level commands that are required to make these changes. Programmatically, a tag can be created with the facade interface IXMLTagCommands, which has a method CreateTag. See the figure “Creating a tag” on page 45, which shows code from the file SnpPerformXMLTags.cpp in the folder <sdk>/source/sdksamples/codesnippets. On executing this code successfully, createdTagUID is the UID of an instance of kXMLTagBoss. FIGURE 29 Creating a tag // Let tagName specify desired tag name UID tagColorUID = kInvalidUID; // let the application pick a colour Utils<IXMLTagCommands> tagCommands; UID createdTagUID = kInvalidUID; ErrorCode createErr = tagCommands->CreateTag (::GetUIDRef(tagList), tagName, tagColorUID, &createdTagUID); Under the hood, the low-level commands kXMLCreateTagCmdBoss and kXMLSetTagColorCmdBoss are processed. If you want to see the notification scheme for these commands, consult the table “Low-level command notification details” on page 87. You can delete tags and update the properties of tags using the facade interface IXMLTagCommands, aggregated on the boss class named kUtilsBoss. Under the hood, deleting a tag processes the low-level command kXMLDeleteTagCmdBoss. See the table “Low-level command notification details” on page 87 if you want to be notified when this change happens. XML Productivity Features 45 XML Productivity Features Mappings between tags and run-styles Mappings between tags and run-styles Feature description FIGURE 30 User interface for mapping tags to styles An end-user can choose to apply a mapping between element names and run-styles (character and paragraph styles). Once the mapping is applied to a document, then any marked-up text will be styled as specified by the style on the right-hand-side of this mapping. An important use-case for mapping tags-to-styles is to prepare a document for XML import; assuming that XML-based content does not carry style information, the tag-to-style map is an basic mechanism to apply styling to inbound XML-based content. We are describing it as basic compared to for instance styling based on XSLT or a proprietary mechanism such as Adobe FrameMaker’s Element Definition Document (EDD). The FrameMaker EDD is effectively a style sheet containing rules specifying how to map tags to styles but in a context-dependent way. FIGURE 31 Unstructured document An end-user can apply structure to an unstructured InDesign CS document by choosing to map run-styles to tags. The effect of this is to mark-up the text ranges that have the styles on the left hand side of the style-to-tag mapping. The end-user is warned that applying a style-totag mapping can restructure the document; see the figure entitled “Styles-to-tags user interface” on page 47. 46 XML Productivity Features Mappings between tags and run-styles FIGURE 32 Styles-to-tags user interface Once a style-to-tag mapping has been defined and applied, then ranges of styled text that has the styles referenced will be tagged. Note that there are some default commitments in terms of the tags applied; for instance, the tag “Story” is used for a story, even if this is not present in the tag-list of the document at the time of applying the style-to-tag mapping. FIGURE 33 Structured document after mapping styles to tags Design The tag-to-style map is an associative mapping stored in workspaces (kDocWorkspaceBoss) or kWorkspaceBoss). It is stored in the data interface IXMLTagToStyleMap on the workspace boss classes, and changed via the facade interface IXMLMappingCommands. XML Productivity Features 47 XML Productivity Features Mappings between tags and run-styles FIGURE 34 Structural diagram for tag-to-style map «boss class» kDocWorkspaceBoss 1 IXMLTagToStyleMap::GetTagAt IXMLTagToStyleMap 1 IXMLTagToStyleMap::GetStyleMappedToTag 0..* 0..* «boss class» kXMLTagBoss «boss class» kStyleBoss IXMLTag «boss class» kWorkspaceBoss IXMLTagToStyleMap::GetTagAt 1 This is an associative mapping from a tag (kXMLTagBoss) to style (kStyleBoss) IStyleInfo IXMLTagToStyleMap IXMLTagToStyleMap::GetStyleMappedToTag 1 0..* 0..* «boss class» kXMLTagBoss A document workspace (kDocWorkspaceBoss) and the session workspace (kWorkspaceBoss) store a tag to style mapping in the persistent interface IXMLTagToStyleMap. IXMLTag «boss class» kStyleBoss A style (kStyleBoss) can be a character style or a paragraph style. IStyleInfo The tags (kXMLTagBoss) are also referenced via the tag list (IXMLTagList) on the workspace boss classes. The tags referenced by the tag-to-style map (IXMLTagToStyle) are a subset of those in the tag-list. The model for mapping styles-to-tags is symmetric with the model for mapping styles to tags. It is shown in the figure entitled “Structural diagram for tag-to-style map” on page 48. 48 XML Productivity Features Mappings between tags and run-styles FIGURE 35 Structural diagram for style-to-tag map «boss class» kDocWorkspaceBoss 1 The workspaces maintain an associative mapping, the associations consist of UID-pairs, the LHS being the UID of a style (kStyleBoss) and the RHS being the UID of a tag (kXMLTagBoss). This is stored in the persistent interface IXMLStyleToTagMap. IXMLStyleToTagMap 1 IXMLStyleToTagMap::GetStyleAt IXMLStyleToTagMap::GetTagMappedToStyle 0..* 0..* «boss class» kStyleBoss «boss class» kXMLTagBoss IStyleInfo «boss class» kWorkspaceBoss 1 IXMLStyleToTagMap::GetStyleAt IXMLTag IXMLStyleToTagMap 1 IXMLStyleToTagMap::GetTagMappedToStyle 0..* 0..* «boss class» kStyleBoss «boss class» kXMLTagBoss IStyleInfo Styles (kStyleBoss) can be paragraph or character styles IXMLTag The tags are also referenced from each workspace via the tag-list (IXMLTagList). However, only those that participate in the style-to-tag mapping are linked via the association maintained by IXMLStyleToTagMap Creating and modifying the mapping from tag to run-style This mapping is stored in the interface IXMLTagToStyleMap on the document workspace (kDocWorkspaceBoss) and session workspace (kWorkspaceBoss). It can be changed from your code through methods on the command facade IXMLMappingCommands, on kUtilsBoss. Under the hood, modifying the tag-to-style map processes low-level commands like kXMLMapTagToStyleCmdBoss, kXMLUnMapTagToStyleCmdBoss; see the table entitled XML Productivity Features 49 XML Productivity Features Mappings between tags and run-styles “Low-level command notification details” on page 87 for details on how to observe notifications sent by these commands. See <sdk>/source/sdksamples/codesnippets/SnpPerformXMLTagAndStyle.cpp for an example of using these low-level commands in context. Creating and modifying the mapping from run-style to tag This mapping is stored in the interface IXMLStyleToTagMap on the document workspace (kDocWorkspaceBoss). It can be changed from your code through methods on the command facade IXMLMappingCommands, on kUtilsBoss. Under the hood, changing the style-to-tag map can result in the low-level commands such as kXMLMapStyleToTagCmdBoss, kXMLUnMapStyleToTagCmdBoss being processed; see the table entitled “Low-level command notification details” on page 87 for details on how to observe notifications sent by these commands. See <sdk>/source/sdksamples/codesnippets/SnpPerformXMLTagAndStyle.cpp for an example of using these low-level commands in context. Applying a mapping Even if you have added new associations to the mapping between tags and styles, the document would not appear to be any different; you need to apply the mapping to the document. At present you need to process a low level command to do this. The low-level command kXMLApplyTagToStyleMappingCmdBoss can be processed to apply a tag to style map to a document. See the SDK sample named XDocBookWorkflow for an instance of this command being processed in context. FIGURE 36 Applying tag to style map // Assume you have a reference to a document, IDocument* InterfacePtr<ICommand> cmd( CmdUtils::CreateCommand(kXMLApplyTagToStyleMappingCmdBoss)); cmd->SetItemList(UIDList(document)); CmdUtils::ProcessCommand(cmd); Alternatively, you might copy the mapping from your own custom boss object with an IXMLTagToStyleMap interface via the command facade IXMLMappingCommands. At the time of writing there is no corresponding low-level command to apply a style-to-tag mapping. At the time of writing, this is done by copying a mapping stored in an instance of a dialog boss class (kStyleToTagMappingDialogBoss) to the workspace. If you wanted to automate style-to-tag mapping, then you would have to define a class that aggregated IXMLStyleToTagMap and then use IXMLMappingCommands to copy a mapping from an instance of this class to a document workspace. 50 XML Productivity Features Changing logical structure Changing logical structure Feature description The logical structure is also changed when importing XML (see “Importing XML” on page 35) or when applying a style-to-tag map (see “Creating and modifying the mapping from run-style to tag” on page 50). The logical structure is also changed when content items are tagged; for instance, see the use cases “Tagging placeholder graphics frame for an image” on page 53 and “Tagging text and graphics” on page 60. The logical structure can also be changed directly, e.g. by an end-user, through the structure-view, or programmatically; elements can be created that are not associated with content items as “structural elements”; see “Adding structural elements” on page 54. Changing logical structure by tagging content To tag a placeholder item, the end-user creates a graphics frame, e.g. with the Rectangle tool, and then chooses a tag to apply to this frame; for instance, they might tag it with “Image” to indicate that the frame was to be populated with image-based content. When a document object such as a graphic frame is tagged, then a new element is created in the logical structure. There are two decisions that need to be made; 1. what the parent of the new element should be, 2. where the new element should be in the ordered collection of siblings of its new parent. This section defines some of the rules that are used to decide where in the element tree a new element is placed. Consider the case of tagging a graphic frame as a placeholder. 1. If there are no tagged objects in the document, then a new element is created that is a child of the root element. 2. If there are already tagged objects in the document, then a new element is created that is the last sibling of the root element. The logical structure can be re-ordered either through the user-interface or programmatically, through command facades like IXMLElementCommands. It is also possible to add a new unplaced element anywhere into the logical structure using either the structure-view user-interface, or using IXMLElementCommands. This can then be associated with a document object using either a gesture, or programmatically. In most cases, the document model does not constrain the logical structure; an exception is in the case of tagging a text range, which requires the containing story (kTextStoryBoss) be tagged. The element that is associated with the tagged text range is added a child of the element in the structure that is associated with the tagged story. An end-user can create a new element in the logical structure by executing the menu item “New element” on the Structure pop-out menu on the Structure View window. The behaviour of this menu item is not straightforward, since different behaviour results depending on XML Productivity Features 51 XML Productivity Features Changing logical structure whether the element in the structure-view is already placed, and if placed what the associated content item is. The following scenarios can be identified below. 1. The root element is selected in the structure view, and the user executes the “New element” menu item. FIGURE 37 Before adding new element In this case, the application adds a child element to the logical structure’s root element. The child element by default is added at the end of the collection of child elements of the root element. For example, the root element ‘book’ in the figure entitled “Before adding new element” on page 52 is selected and a new element ‘article’ is added. The new element is inserted into the logical structure as the last child of the root element and it is shown as unplaced content, since the top level element was not placed; only its child elements are placed content. FIGURE 38 52 After inserting new element 2. There is a selection in the structure view window that is an element mapped to a story (kTextStoryBoss), and the user executes the “New element” menu item. This results in the user creating a element in the logical structure which is associated with a text range in the story except that the text range is of zero-length. The element is shown as placed, because it has an association with story content, albeit an empty text range. 3. There is an element selected in the structure view window associated with a graphic placeholder frame and the user executes the “New element” menu item. This creates an element that is a child of the selected element; however it has the net effect of turning the XML Productivity Features Changing logical structure graphic frame into a text frame. That is, creating a new element in the structure-view window when the element selected represents a graphic frame has the effect of turning the graphic frame into a text frame. The object that stores the reference to the new element in the structure view is a story (kTextStoryBoss). So the “New element” action in this case has the net effect of tagging a story, which is as if the user had clicked in the graphic frame with the text tool to convert its type. 4. If there is an unplaced image element selected in the structure view is already an image, e.g. has the default “href ” attribute that references a path in the local file system, then there is a warning about turning the graphic frame into a text frame. If the element in the structure view represents an image that is already placed, then the end-user can’t execute “New element” anyway. FIGURE 39 Turning an unplaced image into a text element The “New element” option is unavailable when there is a layout selection, when there is a nonempty text selection, or when there is already a placed image in the structure view. An end-user can add an element to the logical structure in either the structure view, in which case the element is not directly associated with document content, or in another view such as the document layout, by tagging some content item; for instance, a text range or a graphic placeholder frame. See the associated use cases “Tagging placeholder graphics frame for an image” on page 53 and “Tagging text and graphics” on page 60. Tagging placeholder graphics frame for an image FIGURE 40 Minimal XML content to place an image <?xml version="1.0" encoding="UTF-8" ?> - <Root> <Image href="file://testfile.tif" /> </Root> The example in the figure entitled “Minimal XML file to be imported” on page 17 shows an example of XML for importing an image by reference. On importing the XML file, if we do not have a pre-existing placeholder graphic frame tagged with “Image”, the image would not be placed. XML Productivity Features 53 XML Productivity Features Changing logical structure FIGURE 41 Unplaced image If there is a pre-existing graphic frame tagged “Image”, then the image would be placed on import. One constraint is that if you intend an image to be placed in the graphic frame, then the element “Image” (for this example) must support the attribute “href ” that on import should specify the system path to locate the image to be placed, or you will have to do extra work to place the image yourself. FIGURE 42 Placed image You can customize the XML import to support placing images that are referred to by different means; for instance, the sample XDocBookWorkflow places images based on an attribute named “fileref ” (from DocBook). You could also customize this using the XSL transform feature, described in “Walkthrough: transforming imported XML with XSLT” on page 70, or using a custom SAX content handler, described in “Custom SAX Content handler” on page 75. Adding structural elements An end-user can add new elements to the logical structure of a document using the structureview and its associated pop-out menu. Elements created in this way are not immediately associated with content items and are therefore unplaced. However, unlike content that has been imported, there is no content associated with these elements when they are created. You might be wondering why this is a significant use case; one reason that an end-user might create elements in this way would be for creating “structural” elements that specified the logical structure of a document and provided placeholders into which content could be placed. FIGURE 43 Creating elements as structural elements For instance, suppose that the content model for your publication is as a collection of “Section” elements (e.g. Arts, Motoring etc.), but that each “Article” is worked on independently in the editorial system, and imported/placed one at a time into the correct section. You might have an element “Section” that consisted of a set of “Article” elements; the “Section” element might never itself have any content but be used to structure the collection of Article elements. The XML template for this publication might be set up as shown in the figure entitled “Creating elements as structural elements” on page 54. Note that the Article elements 54 XML Productivity Features Changing logical structure show as placed content because these have been associated with linked text frames, but these are placeholders into which the XML-based articles would be imported, with a top-level element of Article. To create new elements in the logical structure as an end-user, a selection is required in the structure-view to indicate the element that is parent of the newly created element. Design Taggability The suite named IXMLTagSuite can be used to tag a selection, such as a placeholder graphic frame. The precondition is that the target of the selection can be tagged, which is relatively complex to evaluate. The utility interface IXMLUtils has a method IsTaggablePageItem that allows client code to determine whether a given boss object can be tagged. There is also a method on IXMLUtils named GetActualContent, which lets client code acquire a reference (UIDRef) to the underlying boss object supporting the tagging operation. This is an instance of a boss class that aggregates IXMLReferenceData. XML Productivity Features 55 XML Productivity Features Changing logical structure Tagging graphics FIGURE 44 «boss class» kSplineItemBoss Structural diagram for tagging placeholder item IGraphicFrameData IHierarchy Backing store 1 «helper class» XMLReference Instantiate() IHierarchy::GetChildUID 0..1 «boss class» kTextXMLElementBoss IIDXMLElement 1 IIDXMLElement::GetTagUID 0..1 «boss class» kPlaceHolderItemBoss 1 1 IXMLReferenceData «boss class» kXMLTagBoss Represents the name of tag and colour of the tag as it appears in the UI. When a graphic frame is created as a target for content, e.g. an image, it initially has a dependent that is an instance of kPlaceholderItemBoss. This disappears once content is placed, becoming e.g. kMultiColumnItemBoss or kImageItem or whatever, depending on the type of content that is placed A basic XML-related use case is tagging a placeholder graphic frame (see “Tagging placeholder graphics frame for an image” on page 53. When an XML tag is applied to a graphic frame with placeholder content, e.g. kSplineItemBoss with a kPlaceHolderItemBoss, then a new instance of the class kTextXMLElementBoss is created and a link created between this object and the boss object representing the placeholder item (kPlaceHolderItemBoss). This association is shown in the figure entitled “Tagging placeholder graphics frame for an image” on page 53. When an end-user tags a graphic frame as a placeholder, the structure-view draws a cross through the icon representing the element, to indicate its placeholder status. Client code can implement this using IXMLTagSuite::SetTag when there is a layout selection set; for instance, you can create one programmatically with ILayoutSelectionSuite. See also IXMLElementCommands::CreateElement methods, which are a facade onto the underlying low-level commands that create the new objects in the logical structure, change the native document model and create associations between the logical structure and the native document model. 56 XML Productivity Features Changing logical structure Tagging text It is not possible to “tag a text frame” with InDesign CS in a meaningful way. When the enduser makes a gesture to tag a text frame, the net result is that the user tags the story (kTextStoryBoss) that flows through the frame. There are scenarios that make an end-user believe that they have tagged a text frame, and the end-user (help) documentation mentions tagging a text frame; however, you should always hold in mind that the story is the target for the tagging operation. Consider the following scenarios: 1. creating a text frame with the text tool, changing to the pointer tool and selecting the empty text frame, then applying a tag 2. creating a text frame with the text tool, leaving the insertion point in the newly created text frame, then applying a tag 3. creating a text frame with the text tool, entering text, selecting all the text in the frame through a select-all gesture, then applying a tag Although an end-user may believe that they are tagging a text frame, which is a layout object that is a container for text, in reality, in each of the above scenarios, they are tagging the story (kTextStoryBoss) that flows through the text frame. Consider the scenario (2) where there is an insertion point an un-tagged frame and a user wants to apply a tag, which they think is being applied to the text frame. In this case, the text frame might be represented by a kSplineItemBoss, with its first child a kMultiColumnItemBoss, and its first child in turn a kFrameItemBoss. Note that none of these boss classes aggregate IXMLReferenceData and therefore cannot be associated with an element in the logical structure. A boss class participating in the text frame model that can be associated with an element in the logical structure is the story, kTextStoryBoss. Scenario (3) is similar to scenario (2), except that (2) is a degenerate case where a zero-length story is “selected”. An end-user can select a text range and apply a tag to mark-up the text range. At the time of writing, the following text ranges cannot be tagged: 1. table cell text, 2. inlines; graphics, notes, tracked changes, table frames, hyperlinks. See boss classes that aggregate IOwnedItem, 3. Ruby text annotations in Japanese, 4. text in locked stories (see ITextLockData, InCopy Bridge). If the text frame where the text selection exists is not associated with an element in the logical structure, the end-user is prompted with a slightly misleading “Tag frame” dialog. In reality the element that is chosen is associated with the story (kTextStoryBoss). XML Productivity Features 57 XML Productivity Features Changing logical structure FIGURE 45 Tagging a range of text A tag is applied to a text range by an end-user by making a text selection, and then either clicking in the Tags panel on a particular tag, or selecting an item from a context-sensitive menu containing the names of the tags. Once the range is tagged, tag markers are placed before and after the tagged range. An example is shown in the figure entitled “Tagging a range of text” on page 58. The [ and ] characters are non-printing, zero-width spaces inserted into the text, which can be shown or hidden. Note that in this example, the tag “article” has been applied to the story, and “emphasis” to the text range containing the characters “tagged”. FIGURE 46 Tagged text range K4EXT8-,%LEMENT"OSS K4EXT3TORY"OSS K8-,4AG"OSS K3PLINE)TEM"OSS K-ULTI#OLUMN)TEM"OSS K&RAME)TEM"OSS Consider the minimal example of tagging a text range, shown in the figure “Tagged text range” on page 58. Of the classes shown (kSplineItemBoss, etc.) that participate in the native document model, only kTextStoryBoss aggregates IXMLReferenceData. Although the enduser is shown a dialog to choose a tag for the text frame when they try to tag a range, the tag is really applied to the story (kTextStoryBoss). The boss class kTextStoryBoss represents a flow of styled text, as well as having special responsibilities as the owner of the backing store (kSBOSPageBoss). When a story is tagged, the IXMLReferenceData interface on the story (kTextStoryBoss) is populated with a reference an object (kTextXMLElementBoss) in the logical structure. 58 XML Productivity Features Changing logical structure FIGURE 47 Structural diagram for tagging a story Obtain instance of XMLReference from IXMLReferenceData to navigate from content item to object representing element in the logical structure If a story has been tagged then the interface IXMLReferenceData will refer to the element that is the root of the logical structure within the story «helper class» XMLReference Instantiate() Backing store «boss class» kTextStoryBoss 0..1 1 IXMLReferenceData 0..1 IIDXMLElement::GetContentItem «boss class» kTextXMLElementBoss 1 IIDXMLElement 1 IIDXMLElement::GetTagUID 1 «boss class» kXMLTagBoss IXMLTag The story (kTextStoryBoss) in which the text range is contained must be tagged before a range of text can be tagged; this creates an association of the kind shown in “Structural diagram for tagging a story” on page 59. The logical sequence of events when tagging a text range in an un-tagged story is: 1. the story (kTextStoryBoss) is tagged. This involves creating an instance of kTextXMLElementBoss in the root backing store (see “Backing store” on page 84) to represent an element in the logical structure. In the example shown in the figure “Tagged text range” on page 58, the root element has the tag “article”. 2. An instance of kTextXMLElementBoss is created in the story’s own backing store to represent an element in the logical structure. In the example above, this is the “emphasis” element. Characters are inserted into the text model to represent the start and end of the tagged text range. These are represented in the API by kTextChar_ZeroSpaceNoBreak [see the SDK header file named public/includes/TextChar.h]. XML Productivity Features 59 XML Productivity Features Changing logical structure 3. The instance of kTextXMLElementBoss created to represent the element associated with the text range tagged stores the start and end of the text range. The data stored can be accessed through methods like IXMLUtils::GetElementIndices(). The use case is described in the section “Tagging text and graphics” on page 60. Structural elements When creating elements in the logical structure that are not based on importing external content and are not immediately associated with content items in the document, the elements are added to the backing store containing the parent element. When the parent is the root element, then the root backing store would contain the newly created elements. The design for creating elements unplaced in the logical structure is the same as that for “Structural diagram for tagging placeholder item” on page 56, with the exception that there is no initial association with a content item. In other words, IIDXMLElement::GetContentItem would return kInvalidUID for the newly created elements. Creating, updating and deleting elements and attributes One way to add and remove elements from the logical structure is to use the suite interface IXMLNodeSelectionSuite to program a selection in the structure-view, and then IXMLStructureSuite, which acts on a selection in the structure view. The command facade IXMLElementCommands provides methods (CreateElement overloads) to create a new element in the logical structure not associated with a content item. It also provides a method (DeleteElementAndContent) to delete elements in the logical structure. Removing an element associated with placed content means that the corresponding layout items may be deleted. Under the hood, when an element is created, the low-level command kXMLCreateElementCmdBoss is processed, and when it is deleted, the low-level command kXMLDeleteElementCmdBoss is processed. See the table “Low-level command notification details” on page 87 for more details on how to observe these operations taking place. You can move elements in the logical structure using methods on IXMLElementCommands, and you can also place elements from the logical structure using methods on this interface. Moving elements in the logical structure may affect the native document model; however you can make some changes in the logical structure without affecting the native document model. For instance, if you have two stories that are tagged, then re-ordering the elements corresponding to the two stories does not affect the native document model, only the logical structure. Creating, updating and deleting attributes can be done using methods on IXMLAttributeCommands. Tagging text and graphics A text range can be tagged programmatically using the interface IXMLElementCommands, aggregated on kUtilsBoss; this creates an instance of the class kTextXMLElementBoss for each tagged range. To tag a text range or a story (kTextStoryBoss) programmatically, there are 60 XML Productivity Features DTD and validation CreateElement methods on the command facade IXMLElementCommands (on kUtilsBoss) that can be used. There are methods on the utility interface named IXMLUtils that allow you to determine the element associated with a range of tagged text, once a tag has been applied. You can tag a graphic frame as a placeholder for an image programmatically using IXMLElementCommands; look for the methods that have the parameter “UID contentItem” in their method signature. You can also use the interface IXMLTagSuite if there is a selection in the structure-view, which you can create programmatically with IXMLNodeSelectionSuite. See <sdk>/source/sdksamples/codesnippets/SnpPerformXMLElements.cpp for code that tags content items. You should also see the SDK sample XMLMarkupInjector in the folder <sdk>/source/sdksamples/xmlmarkupinjector, which tags text-ranges in non-trivial ways. DTD and validation Feature description An end-user can import a DTD to create an association between the DTD and the document logical structure, using the pop-out menu on the Structure panel. This associates the DTD with the logical structure of the document. This also has the net effect of creating new tags in the tag-list for elements defined in the logical structure; see “Tags and the tag-list” on page 41. At the time of writing (InDesign CS), this does not create tags for those elements defined within entities in the DTD. FIGURE 48 Tags added after importing DTD The figure entitled “Tags added after importing DTD” on page 61 shows tags created by importing a DTD, in this case the example shown in “Basic grammar for article-based publications” on page 89. Note how a visual indicator appears beside the tags created by importing the DTD (article, article-title etc.). XML Productivity Features 61 XML Productivity Features DTD and validation FIGURE 49 Validation error screenshot An end-user can validate the logical structure of a document against a DTD once they have associated a DTD with it. This results in any validation errors being shown in a window below the structure-view; see the figure entitled “Validation error screenshot” on page 62. This contains hyperlinks; if the end-user clicks on these hyperlinks, InDesign CS can automatically fix the validation errors, although this may not always have the desired effect (for instance, it may delete content that was incorrectly tagged given the grammar). At the time of writing, the API does not support validating the logical structure of an InDesign CS document against an XML schema [http://www.w3.org/TR/xmlschema-0/]. Design A DTD associated with the logical structure of a document is represented by the class kXMLDTDBoss. It is responsible for maintaining an association with a collection of tag objects (kXMLTagBoss). These kXMLTagBoss objects are created with the names of elements defined in the grammar, at least those that are defined outwith entities. 62 XML Productivity Features DTD and validation FIGURE 50 Structural diagram involving DTD element «boss class» kTextStoryBoss Instance of non-user accessible story that owns the backing store 1 owns 1 «boss class» kSBOSPageBoss Root backing store for the document 1 hasDTD 0..1 tags «boss class» kXMLDTDBoss 1 «boss class» kXMLTagBoss 1..* No public API to this class of interest The class responsible for the behaviour of the DTD element is associated with the set of tags (kXMLTagBoss) for the elements defined in the DTD Associate DTD You can associate a DTD with a document by processing a low level command (an instance of the class kXMLLoadDTDCmdBoss). See the figure entitled “Associating a DTD with a document” on page 63. Associating a DTD with a document has the effect of creating another element in the root backing store for the document, an instance of class kXMLDTDBoss. FIGURE 51 Associating a DTD with a document InterfacePtr<ICommand> loadDTDCmd(CmdUtils::CreateCommand(kXMLLoadDTDCmdBoss)); InterfacePtr<IXMLLoadDTDCmdData> loadDTDData(loadDTDCmd, UseDefaultIID()); loadDTDData->Set(sysFile, document); ErrorCode err = CmdUtils::ProcessCommand(loadDTDCmd); Validate against DTD There are two main ways to validate the logical structure of a document against a DTD: XML Productivity Features 63 XML Productivity Features Processing instructions and comments 1. Use the action manager (IActionManager) to perform the equivalent action to when the corresponding Structure menu item is executed (kStructureValidateRootActionID to validate from the root, for instance). 2. You can validate the logical structure using the suite interface IXMLStructureSuite, which has methods relating to validation. The ActionID for the action to validate the entire logical structure from the root is kStructureValidateRootActionID. See source/public/includes/XMediaUIID.h for this and related identifiers. Code that would perform this is shown in the figure “Validating the logical structure” on page 64. FIGURE 52 Validating the logical structure // Assume that you have an activeContext (IActiveContext*) on entry InterfacePtr<IApplication> theApp(gSession->QueryApplication()); InterfacePtr<IActionManager> actionMgr(theApp->QueryActionManager()); actionMgr->PerformAction(activeContext, kStructureValidateRootActionID); The suite interface IXMLStructureSuite offers methods CanValidateSelection (you should test this precondition) and ValidateSelection. The method ValidateSelection requires you to take responsibility for handling (e.g. displaying) the errors discovered on validation. To execute this method, you need to supply an IXMLValidator interface pointer, which is a reference to the boss object (kXMLDocumentBoss) responsible for performing the validation and storing the results. To acquire the interface IXMLValidator (on kXMLDocumentBoss) you would write: InterfacePtr<IIDXMLElement> docElement(Utils<IXMLUtils>()->QueryDocElement(db)); InterfacePtr<IXMLValidator> xmlValidator(docElement, UseDefaultIID()); When the validation has run, the interface IXMLValidator can be used to access to a collection of instances of XMLDTDValidationError containing information about the errors. Processing instructions and comments Feature description XML comments (see [http://www.w3.org/TR/REC-xml#sec-comments]) can appear anywhere inside a document, outside of other mark-up. They can also appear inside the document type declaration at places allowed by the grammar for defining a DTD. For instance: <!-- This is a comment --> Processing instructions (see [http://www.w3.org/TR/REC-xml#sec-pi]) allow XML-based documents to contain instructions for applications that process them. XML-capable applications like Adobe FrameMaker (in structured mode) use processing instructions to preserve specialised types of content in XML documents. For instance: <?FM MARKER [Index] translating, PIs?> is a PI generated by FrameMaker on export to specify an index-term with the text “translating, PIs”. It is possible to create new processing instructions anywhere within the logical structure. 64 XML Productivity Features Processing instructions and comments FIGURE 53 Processing instruction in the structure-view An end-user can add XML-comments and processing instructions to the logical structure if there is a selection in the structure-view. Design The backing store that is used depends on where in the logical structure the comment or processing instructions are to be created. «boss class» kTextStoryBoss 1 If they are immediate children of the root or in an unplaced hierarchy starting from the root, then they would be present in the root backing store. owns 1 Otherwise they would be found in the backing store associated with their parent element. «boss class» kSBOSPageBoss stores 1 1 stores 0..* 0..* «boss class» kXMLCommentBoss IStringData This data interface stores the text of the comment «boss class» kXMLPIBoss IStringData (IID_IXMLPITARGET) IStringData (IID_IXMLPIDATA) These data interfaces store the processing target (e.g. "FM") and the data for the instruction respectively. XML comments are represented by the class kXMLCommentBoss. The IStringData interface of this class is responsible for storing the text of the comment. Processing instructions are represented by the class kXMLPIBoss; a processing instruction appears to the user as a key-value pair {target, data}. There are two IStringData interfaces on this class, which represent the processing target (IID_IXMLPITARGET) and the data for the instruction (IID_IXMLPIDATA). XML Productivity Features 65 XML Productivity Features User interface Adding comments and processing instructions You should determine if it is possible to add a new comment given the selection in the structure-view with IXMLTagSuite::CanAddComment.To create a new XML comment, you can use IXMLTagSuite::AddComment. Under the hood, this processes the low-level command kXMLCreateCommentCmdBoss, creating an instance of kXMLCommentBoss at the appropriate location in the logical structure. See the table entitled “Low-level command notification details” on page 87 for information on observing this command being processed. To create a new processing instruction, you can use AddProcessingInstruction on IXMLTagSuite. Under the hood, this processes the low-level command kXMLCreatePICmdBoss to create a new instance of the boss class kXMLPIBoss in the logical structure. See the table entitled “Low-level command notification details” on page 87 for information on observing this command being processed. There are other methods on IXMLTagSuite that allow you to change the key-value pair stored with a processing instruction or delete the processing instruction. User interface Feature description FIGURE 54 Structure-view: showing text snippets The structure-view window creates a rendering of the logical structure of a document and lets an end-user interact with the logical structure. It may be desirable to control the visibility and other properties of this window, depending on your workflow. Also since you can make selections within the structure-view programmatically (see “How do I make a selection in the structure view?” on page 78), you may have a workflow that depends on the view that supports this suite being active. 66 XML Productivity Features User interface Design FIGURE 55 IXMLPreferences Preferences relating to the structure-view «boss class» kWorkspaceBoss IStructureViewPrefs IDocStructurePrefs «boss class» kDocWorkspaceBoss IDocStructurePrefs The XML view-preferences are split across the two workspaces. The document-specific preferences, such as whether the structure-view is on show for a given document, are held in IDocStructurePrefs, found on both session and document workspaces. There are other session-level view preferences e.g. whether to show text snippets (IStructureViewPrefs) or whether to show tagged frames (IXMLPreferences) There is an interface named IDocStructurePrefs that controls the properties of the structureview and the validation errors window, relating to whether they are visible. There is a separate interface called IStructureViewPrefs that stores other properties the structure-view window, such as whether text snippets are to be shown, as in the figure entitled “Structure-view: showing text snippets” on page 66. There is also an interface named IXMLPreferences on the session workspace (kWorkspaceBoss) that determines the visibility of tag-markers and whether to show tagged page items in a different colour to other page items. Visibility of the structure-view The approach that you can take is to ask the action manager (IActionManager) to perform an action on your behalf (kOpenStructureWinActionID), which will process the low-level command to change the preference relating to the structure-view window (IDocStructurePrefs) and update the state of the structure-view window, showing the structure-view if it is hidden and hiding the structure-view if it is showing. Despite the action name, if the structure-view is already open before you execute this code, this will close it. FIGURE 56 Processing action to toggle structure-view visibility // Assume activeContext is a variable of type IActiveContext* // referring to the active context InterfacePtr<IApplication> app(gSession->QueryApplication()); InterfacePtr<IActionManager> actionManager(app->QueryActionManager()); actionManager->PerformAction(activeContext, kOpenStructureWinActionID); There is a low-level command named kChangeDocStructurePrefsCmdBoss that changes the preferences relating to the structure view window (IDocStructurePrefs); see “Preferences relating to the structure-view” on page 67. However there is no public API to make it easy to XML Productivity Features 67 XML Productivity Features XSL support translate changing these preferences into the action of showing/hiding the structure view. These preferences are stored in both the session workspace (kWorkspaceBoss) and the document workspace (kDocWorkspaceBoss) to customize the visibility of the structure-view on a per document basis. Appearance of the structure-view Some structure-view preferences stored in IStructureViewPrefs (on the session workspace only, kWorkspaceBoss); these control the appearance of the structure-view when it is visible. The appearance is controlled by preferences stored in IStructureViewPrefs on the session workspace (kWorkspaceBoss). You can change these in one of two ways: 1. Ask the action manager (IActionManager) to perform the appropriate action. 2. Process the low-level command that changes the data stored on this interface yourself. For instance, to toggle the visibility of text snippets in the logical structure view, you can ask the action manager to perform the action kStructureShowTextSnippetsActionID or process the low-level command kChangeStructureViewPrefsCmdBoss and set up IStructureViewPrefs on the command yourself to reflect your intent. To perform the action kStructureShowTextSnippetsActionID, you would write code similar to that in the figure“Processing action to toggle structure-view visibility” on page 67. The method to process the low-level command would involve writing code like this: FIGURE 57 Processing command to change structure-view appearance InterfacePtr<IStructureViewPrefs>prefs( static_cast<IStructureViewPrefs*>( ::QueryPreferences(IStructureViewPrefs::kDefaultIID, kGetSessionPrefs))); InterfacePtr<ICommand>cmd( CmdUtils::CreateCommand(kChangeStructureViewPrefsCmdBoss));InterfacePtr<IStructureV iewPrefs>cmdPrefs(cmd, UseDefaultIID()); cmdPrefs->Copy(prefs); cmdPrefs->SetShowTextSnippets( !prefs->ShowTextSnippets() ); cmd->SetItemList( ::GetUIDRef(prefs) ); CmdUtils::ProcessCommand(cmd); XSL support Feature description Since version CS, the applications can transform imported XML by applying an XSLT style sheet; this only happens during the import process by default. This feature support workflows where content for import can be represented in a variety of XML languages but a single XMLbased template is used throughout and the XML must be transformed on import to match the grammar the XML-template expects. 68 XML Productivity Features XSL support Design The service (with ServiceID of (kDataServices) that can transform an incoming XML file via XSLT depends on an XSL enabler service (kXSLEnablerService) being available. The XSLT transform is not applied if an XSL enabler service cannot be located. You must implement your own XSL enabler service that turns on the XSL-transform feature; see the section “Extension points” on page 73, since the application does not ship with this service. Transforming imported XML To make the application transform imported XML via an XSL style sheet, you must: 1. Make sure that you have provided an XSL enabler service. 2. Process the low-level import XML file command yourself and set up the data interface (IStylesheetData) on the import XML command to reference the XSL style that you want to import. The binding between the low-level command responsible for importing XML (kImportXMLFileCmdBoss) and the XSLT transform is via a service provider with ServiceID of kDataServices. This has the service interface named IDataServices, with a method TransformContent. The transform can only happen if it can locate a service provider kXSLEnablerService. A code fragment setting up the IStylesheetData interface and processing the low-level import XML file command is shown in the figure entitled “Setting the stylesheet for import” on page 69, which imports the XML into the “context document” (from IActiveContext). This will apply the transform in the style sheet if an XSL enabler service is available. FIGURE 58 Setting the stylesheet for import // Assume you have xmlSysFileToImport and stylesheetSysFile on entry, perhaps // through using SDKOpenFileChooser to select them at some stage InterfacePtr<ICommand> importCmd( CmdUtils::CreateCommand( kImportXMLFileCmdBoss)); InterfacePtr<IImportFileCmdData> importCmdData(importCmd, IID_IIMPORTFILECMDDATA); importCmdData->Set(::GetDataBase(ac->GetContextDocument()), xmlSysFileToImport, kSuppressUI); InterfacePtr< IStylesheetData> stylesheetData(importCmd, UseDefaultIID()); stylesheetData->SetFile(stylesheetSysFile); CmdUtils::ProcessCommand(importCmd); There is a rudimentary user-interface already in the application that can be invoked when IXMLImportOptions is set up so that ShouldUseImportFilter() returns kTrue. This can be done by processing the low-level command kChangeXMLImportOptionsCmdBoss. A basic implementation of this is shown in the figure entitled “Changing XML import options” on page 31; a better alternative would be to respect the existing options (by acquiring these before processing the command and setting those on the data interface IXMLImportOption of XML Productivity Features 69 XML Productivity Features Walkthrough: transforming imported XML with XSLT the command) and set only the UseImportFilter(). When the “Import XML” action is executed, then a dialog appears which offers a control into which the platform path of the XSL style sheet to use can be specified. FIGURE 59 Setting XML import options to show import filter // Assume ac is a variable of type IActiveContext* and valid on entry IWorkspace* wkSpc = ac->GetContextWorkspace(); InterfacePtr<ICommand> cmd(CmdUtils::CreateCommand(kChangeXMLImportOptionsCmdBoss)); InterfacePtr< IXMLImportOptions> importOptions(cmd, UseDefaultIID()); cmd->SetItemList(UIDList(wkSpc)); importOptions->SetImportIntoSelected(kTrue); importOptions->SetImportStyle(IXMLImportOptions::kMerge); importOptions->UseImportFilter(); Walkthrough: transforming imported XML with XSLT An implementation that used this feature was carried out, where we took some standard but fairly complex XML language and wrote a style sheet to map it into a simpler grammar on import. A fragment of an NITF file [http://www.nitf.org/] is shown in the figure entitled “XML fragment from NITF file” on page 70. This came from a file on the NITF site; you can find the complete file at [http://www.nitf.org/IPTC/NITF/3.2/examples/nitf-fishing.xml]. FIGURE 60 XML fragment from NITF file <body.content> <media media-type="image" style="align:right"> <media-reference mime-type="image/jpeg" source="high-tide.jpg" alternate-text="The tides are high." he </media-reference> <media-caption> The tides, captured on film late yesterday. </media-caption> <media-producer> Karben </media-producer> </media> <p xml:lang="en-US">The weather was superb today in Norfolk, Virginia. Made me want to take out my boat, manufactured by the <org value="acm" idsrc="iptc.org">Acme Boat Company</org>.</p> <p>Tides in Norfolk are running normal today. This weeks article highlights many of this week's fishing issues, and also presents a reference table of tide times.</p> <hl2>The Tides are High</hl2> <p>As can be seen from the table below, the shores of Oceanview again present the brightest spots for fishermen and sandcastle-builders alike.</p> <nitf-table> <nitf-table-metadata> <nitf-table-summary> <p>This is a table filled with weather data, good for fishermen living in Norfolk, Virginia.</p> </nitf-table-summary> <nitf-col value="beach"/> <nitf-col value="day-high"/> <nitf-col value="day-low"/> <nitf-col occurrences="2" value="tide-time"/> The following steps were carried out as part of this implementation: 70 XML Productivity Features Walkthrough: transforming imported XML with XSLT 1. A basic grammar was defined (see “Basic grammar for publication composed of articles” on page 32) and an instance of an XML file produced by this grammar generated 2. A minimal XSL style sheet was written to map from NITF to our basic grammar with little attempt to extract more than the minimum content. 3. Tags were loaded into an InDesign CS document from the instance of the XML file produced by our basic grammar 4. Paragraph styles were set up matching the names of the tags in the basic grammar, namely article-title, title, subhead, para, and a character style named “emphasis”. A basic grammar was defined as a target language for transforming NITF into; see the figure entitled “Basic grammar for article-based publications” on page 89. This grammar expresses that a publication is composed of articles, composed of an ‘article-title’ and repetitions of the elements title, subhead and para. No attempt is made in this basic example to cater for images or tables, although the extensions required to support these are fairly apparent. See the section “Defaults and constraints” on page 26 for suggestions on how to implement this. The style sheet that was used to turn the NITF into XML conforming to the basic grammar is shown in the figure “Fragment of XSL stylesheet to convert NITF to basic pub” on page 89. The NITF grammar can be downloaded from [http://www.nitf.org/IPTC/NITF/3.2/dtd/nitf-32.dtd]. The document type declaration is documented at [http://www.nitf.org/IPTC/NITF/3.2/documentation/nitf-documentation.html]. Tags were imported from an instance of an XML file generated from the basic grammar. An XML template was set up with paragraph styles matching the tag styles. The low-level command to import XML was processed, setting up the IStylesheetData as necessary to refer to the XSL style sheet. Some points to note about the XSL in the figure entitled “Fragment of XSL stylesheet to convert NITF to basic pub” on page 89 are the use of normalize-space() to normalize the white-space in the XML, and use the xsl:text to force line breaks on import so that InDesign CS will apply the correct paragraph styles. XML Productivity Features 71 XML Productivity Features Walkthrough: transforming imported XML with XSLT FIGURE 61 Result of importing transformed XML An example of the output when the nitf-fishing.xml file in NITF was transformed on import by InDesign CS is shown in the figure “Result of importing transformed XML” on page 72. The example made no attempt to turn the NITF table into a tabular format and removed the nitf-table element with an empty xsl:template. It would be fairly straightforward to respect the table data and transform it into the aid:table content model, by adapting the style sheet at [http://www.nitf.org/IPTC/NITF/3.2/examples/nitf-to-html.xsl]. See the use case “Importing a table” on page 39 for more context. 72 XML Productivity Features Extension points Extension points Custom suite for the structure-view Suites are concerned with manipulating the properties of an abstract selection. A suite exposes an interface that is written to be selection-format agnostic, which lets you work with an abstract selection. It is possible to work either with the selection set by an end-user or programmatically create a selection and then use suite interfaces to manipulate the properties of the selection. If you write a plug-in that interacts with the model behind a selection in any way, you must implement a custom suite. That is, if you need to know (and manipulate) the target of a selection, then you should implement a custom suite. The design of the selection subsystem is already described in some detail in tech-note #10006 on the selection architecture. This material is not intended to rehearse or replace that content, and presumes that you are familiar with that material. If you do not know how to implement a custom suite or what it signifies, then see the selection tech-note (#10006) for clarification. From this point onwards, it is assumed that you are familiar with implementing a custom suite. FIGURE 62 Custom suite for the structure-view ASB «boss class» kIntegratorSuiteBoss You need to provide implementations of your interface on the "abstract" suite boss (kIntegratorSuiteBoss) and the "concrete" suite boss (in this case kXMLStructureSuiteBoss). IYourCustomSuite CSB «boss class» kXMLStructureSuiteBoss IYourCustomSuite IXMLNodeTarget If you wanted to implement your own custom suite that was available whenever there was a selection in the structure-view, then you would need to follow the pattern of IXMLStructureSuite, and add-in your custom suite to both kIntegratorSuiteBoss (ASB in terms of the selection architecture) and kXMLStructureSuiteBoss (CSB). You are not able to share (re-use) one implementation of your suite interface for the add-ins to the different boss classes, because each implementation of your custom suite interface is tied to one selection format. The implementation associated with the ASB is normally based on templates in the API and the code is normally highly stereotyped. However, the implementation added to any CSB that you are interested in works with a specific model format, in this case, a node-set in the logical structure. XML Productivity Features 73 XML Productivity Features Extension points For instance, suppose that you wanted to write a custom suite that verified the image references in the nodes selected. When you implement a custom suite, it gives you access to the nodes selected in the structure view. These are represented by IXMLNodeTarget. If you add-in your custom suite to the CSB kXMLStructureSuiteBoss, then the interface IXMLNodeTarget becomes available to your custom suite implementation code, at least, to the implementation behind the interface you have added to the CSB. This is illustrated in the figure entitled “Custom suite for the structure-view” on page 73. XSL Enabler FIGURE 63 XSL Enabler service provider «boss class» kYourCustomXSLEnablerServiceBoss «interface» IK2ServiceProvider HasMultipleIDs () GetServiceID() GetServiceIDs(out serviceIDs : K2Vector<ServiceID>) «partial implementation class» CServiceProvider «interface» IXSLEnabler Enable() Disable() «implementation class» YourCustomXSLEnabler «partial implementation class» YourCustomXSLEnablerSvcProvider GetServiceID() Should return a ServiceID of kXSLEnablerService No partial implementation to assist, so use parameterized type CPMUnknown to implement An XSL enabler is a service provider that returns the Service ID of kXSLEnablerService. The service interface that the service provider boss class should aggregate is IXSLEnabler. The figure entitled “XSL Enabler service provider” on page 74 indicates your responsibilities when implementing this category of service provider. Note that the classes that you are required to provide have names that contain “YourCustom”. 74 XML Productivity Features Extension points To make this fully explicit, the service provider boss class would be defined in your FR file as something like: Class { kXMLBldBlkXSLEnablerServiceBoss, kInvalidClass, { IID_IXSLENABLER,kXMLBldBlkXSLEnablerImpl, IID_IK2SERVICEPROVIDER, kXMLBldBlkServiceProviderImpl, } }, where the string “XMLBldBlk” has replaced “YourCustom”. Custom SAX Content handler A custom SAX content handler lets you read your own content from an XML input stream and take appropriate action. When the application reads an XML stream in importing an XML file, it uses the SAX API [see http://sax.sourceforge.net/]. You can register as a handler for elements in the input XML stream and you are responsible for parsing the element, and its sub-tree as well if you choose. FIGURE 64 Custom SAX content handler «boss class» kYourCustomContentHandlerBoss «interface» ISAXContentHandler Register() StartDocument() EndDocument() StartElement() EndElement() «partial implementation class» CSAXContentHandler «interface» IK2ServiceProvider This must have a ServiceID of kXMLContentHandlerService. Re-use the implementation kXMLContentServiceProviderImpl, of type IK2ServiceProvider «implementation class» YourCustomContentHandler A SAX content handler is a service provider characterised by: 1. the service interface ISAXContentHandler. XML Productivity Features 75 XML Productivity Features Extension points 2. the signature interface IK2ServiceProvider. The ServiceID must be of type kXMLContentHandlerService; you can re-use the API implementation kXMLContentServiceProviderImpl (implementation of IK2ServiceProvider) to do this. The pattern is shown in the figure entitled “Custom SAX content handler” on page 75. Note that you are responsible for the classes whose name contains “YourCustom”. To make this fully explicit, you would define a boss class similar to that shown below, where “YourCustom” has been replaced by “XMLBldBlkCALS”. Class { kXMLBldBlkCALSContentHandlerBoss, kInvalidClass, { IID_IK2SERVICEPROVIDER, kXMLContentServiceProviderImpl, IID_ISAXCONTENTHANDLER,kXMLBldBlkCALSContentHandlerImpl, } }, SAX content handlers are widely used by the application; see boss classes that aggregate the interface named ISAXContentHandler. For instance, the service kXMLTableContentHandlerBoss is responsible for turning content in an aid:table context into a native InDesign CS table; see also “Importing a table” on page 39. The example of the table content handler (kXMLTableContentHandlerBoss) illustrates modifying the default XML-import behaviour of the application, when importing XML-based content. You can also use a SAX content handler just to read XML-based data, without creating elements in the logical structure and/or storing content in a backing store. For instance, panels like the Swatches panel read their options, positions and so on from an XML-file using a SAX content handler. The file “ActiveWorkspace.xml” in the preferences folder for the application contains this XML-based data and is parsed by custom SAX content handlers for each panel. The data is written to the XML file using custom XML generators (IXMLGenerator) for each panel. Custom tag service A tag service is given the opportunity to handle elements in an XML stream that has been opened for reading element names to be used as tags. Why would you want to implement a tag service? For instance, you might have some custom content in the XML file that is created programmatically on export and you do not want end-users to be able to apply the tags based on the element names in your custom content. There is an instance in the API of a tag service named kXMLTableTagContentHandlerBoss; it is used to strip out the table-related tags when loading tags from an XML file. This is because the elements representing a table are added programmatically on export by the application, and end-users should not be able to apply these tags themselves. A tag service is a service provider that is closely related to the SAX content handler service, characterised by: 1. 76 the service interface ISAXContentHandler, XML Productivity Features Extension points 2. the interface IK2ServiceProvider, which should yield a ServiceID of kXMLTagHandlerService. You can re-use of the API implementation named kXMLTagServiceProviderImpl to achieve this. Since you are likely to be using this to filter out names of custom elements that you do not want to appear in the tag-list, you have to provide a minimal implementation of ISAXContentHandler that registers your handler for the elements you want to filter out and claims to handle a sub-tree. You then need do nothing when sent the other ISAXContentHandler messages. Custom SAX entity resolver A custom SAX entity resolver lets you customize entity resolution when a document type (DTD) is being processed by the application’s XML parser. It requires you to not only define a boss class aggregating an interface named ISAXEntityResolver, but you must implement a custom command to associate the DTD with a document that replaces the default command (kXMLLoadDTDCmdBoss) but provides equivalent behaviour. InDesign CS does not, at the time of writing, support resolution of PUBLIC identifiers to entities such as paths on a local file system. For instance, if you want to validate against the DocBook DTD that makes extensive use of PUBLIC identifiers, you would need to implement a custom SAX entity resolver. In the use case “Associate DTD” on page 63, it was mentioned that you can process a command of type kXMLLoadDTDCmdBoss to associate a DTD with the logical structure of an application document. Suppose that you want to work with a document type like DocBook, that uses public identifiers in the DTD. <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd" [...]> By default InDesign CS will not support resolution of a public (external) identifier to a file system identifier, and you will have to implement a custom entity resolver if you want to import XML that depend on public identifiers being correctly resolved for your system. You would also be responsible for writing a custom load DTD command that would let you replace the default entity resolver used by the normal load DTD command to use your own custom variant. To create your own custom entity resolver, it is necessary to deliver a boss class that aggregates the interface ISAXEntityResolver. See the class InCopyDocUtils (InCopyFileActions sample, located in <sdk>/source/sdksamples/incopyfileactions) and the method GetStreamFileType. This uses an instance of a boss class kXMLEmptyEntityResolverBoss to let InCopy, when opening an InCopy XML story file, eliminate the normal behaviour of the default entity resolver (kXMLEntityResolverBoss). XML Productivity Features 77 XML Productivity Features Frequently asked questions Frequently asked questions What is the difference between logical structure and the native document model? The logical structure of an InDesign CS document is a tree-structure, consisting of a tree of elements. An element in the logical structure is represented by a boss classes aggregating an IIDXMLElement interface. See the section “Logical structure” on page 20. The native document model for an InDesign CS document models an end-user’s document as a hierarchy of objects; see “Native document model” on page 81. For instance, the native document model represents spreads, spread-layers, pages, document layers and so on. It is considerably more complex, even for an empty document, than the logical structure. Elements in the logical structure are associated with tags, and can be associated with content items in the native document model if they represent placed content or tagged placeholders. See “Key associations” on page 24. Elements are held in a backing store; see “Backing store” on page 84 It is possible to navigate through the logical structure via just the interface IIDXMLElement. There is no single way to navigate through the native document model; e.g. interfaces such as IHierarchy, ISpread, ISpreadLayer and others may be used for navigation. The logical structure is rendered in the structure-view. The native document model is rendered most completely in the layout view. Other renderings of subsets of the native document model are possible (e.g. Story Editor view). How do I make a selection in the structure view? Suites are facades that make it easier to change the model from client code and represent a “medium-level” API; see “Suites and utilities” on page 34. There are some suite interfaces that can be used to make selections from client code; e.g. ITextSelectionSuite (make a text selection, e.g. a text range within a story), ILayoutSelectionSuite (make a layout selection, e.g. of a graphic frame). There is a corresponding selection suite in the XML subsystem. The interface named IXMLNodeSelectionSuite can be used to select nodes in the structure-view. An instance can be acquired from the selection manager (ISelectionManager) for the structure-view. The interface IXMLNodeSelectionSuite allows you to select objects by XMLReference. This is analogous, but not identical to, selecting objects in the layout view by UID. See the section “Changing logical structure” on page 51 for more detail on working within the logical structure tree. Read the tech-note on the selection architecture (#10006) for more information on the selection subsystem. One of the first problems that you will encounter in working with IXMLNodeSelectionSuite is that you have to acquire the selection manager for the correct view; an end user of InDesign CS typically works in the layout view and the selection manager for this view (on kAbstractLayoutDocumentSelectionBoss ) does not know about IXMLNodeSelectionSuite. The concept of a selection subsystem is tied to that of a view, and for each view, there is a corresponding selection manager (ISelectionManager) 78 XML Productivity Features Frequently asked questions To use IXMLNodeSelectionSuite, you need to acquire the structure-view’s selection manager (the ISelectionManager on kAbstractXMLSelectionBoss ). You need to be sure that the structure-view is visible (see “Visibility of the structure-view” on page 67). If the structureview is visible, then you can acquire a reference to it by knowing the WidgetID for the panel it contains (kXMLPanelWidgetID). A code fragment showing this is given in the figure entitled “Using IXMLNodeSelectionSuite in the structure-view” on page 79. Note that nil interface-ptr checking has been omitted, which in the general case would not be wise, as some of these could be nil, for instance, if the structure-view is not shown. FIGURE 65 Using IXMLNodeSelectionSuite in the structure-view // Assume we have an active context, IActiveContext* // Nil ptr checking is omitted in interests of brevity IDocument* doc = activeContext->GetContextDocument(); InterfacePtr<IWindowList> list(doc, UseDefaultIID()); InterfacePtr<IPanelControlData> docPanelData(list->GetFrontWindow(), UseDefaultIID()); IControlView* view = docPanelData->FindWidget(kXMLPanelWidgetID); Utils<ISelectionUtils>()->ActivateView(view); InterfacePtr<ISelectionManager>selectionMgr( Utils<ISelectionUtils>()->QueryViewSelectionManager(view)); InterfacePtr<IXMLNodeSelectionSuite> xmlNodeSelectionSuite(selectionMgr, UseDefaultIID()); InterfacePtr<IIDXMLElement> rootElement( Utils<IXMLUtils>()->QueryRootElement(doc)); XMLReference rootRef = rootElement->GetXMLReference(); xmlNodeSelectionSuite->SelectElement(rootRef, Selection::kAddTo); How do I create, update or delete elements in the logical structure? One way to do this is to create a selection in the structure view programmatically and then use the suite IXMLStructureSuite, which depends on a selection existing in the structure view. See the FAQ “How do I make a selection in the structure view?” on page 78 for information on how to make a selection in the structure view programmatically. Once you have established a selection in the structure-view, then you can use suites such as IXMLStructureSuite to modify the logical structure. The code fragment in the figure entitled “Code fragment with IXMLStructureSuite” on page 79 shows in outline how this could be done to add an element. To add an element, you need to provide a reference to the tag (by UID) that represents the element’s tag-name. To find out how to create a tag, see the section “Creating, updating and deleting tags” on page 45. FIGURE 66 Code fragment with IXMLStructureSuite // Let ‘doc’ be the document (IDocument*) in which we are working InterfacePtr<IXMLStructureSuite> xmlStructureSuite( static_cast<IXMLStructureSuite* > (Utils<ISelectionUtils>()->QuerySuite( IXMLStructureSuite::kDefaultIID))); if(xmlStructureSuite->CanAddElement ()) { ... create tag for element... ErrorCode err = xmlStructureSuite->AddElement(UIDRef(::GetDataBase(doc), createdTagUID)); ... XML Productivity Features 79 XML Productivity Features Summary and conclusions } If for some reason you do not have a structure-view, e.g. you are working with “headless” documents opened without a view onto them, then you cannot use the method of setting a selection. However, you can still use IXMLElementCommands to create, update and delete elements in the logical structure even when you do not have a view, as this does not depend on having a selection. See “Changing logical structure” on page 51 for more information. How can I read in some arbitrary XML content? The most convenient way to do this is to implement a custom SAX content handler; see the section “Custom SAX Content handler” on page 75. For instance, you might want to import some XML-based content into the document such as a table defined in CALS table format, which is not supported by InDesign CS without writing such an extension. Alternatively, you might have configuration data expressed in XML; the palettes read their positions and other properties through a custom SAX content handler. How do I validate an XML document from within the applications? You can associate a DTD with a document programmatically and then ask the applications to validate the logical structure of the document against the DTD. See the section “DTD and validation” on page 61 How do I change the XML import options? Process the low-level command kChangeXMLImportOptionsCmdBoss; this changes the data stored on the interface IXMLImportOptions. See also the section “Importing XML data” on page 38 Summary and conclusions This document has explored programming with the XML API of InDesign CS. Using XML in conjunction with InDesign CS has some benefits for programmers, which include the following: 80 • It is relatively easy to pre-process XML for import into InDesign CS. There are numerous mature XML-toolkits for diverse programming languages; see for instance [http://xml.coverpages.org/software.html] for listings. • Importing graphics into tagged placeholders is a convenient way to place graphics without writing very much, if any, code. • Importing tables from an XML data file is again a convenient way to import rich content without having to write very much, if any, code • The XML API of InDesign CS is well-documented; in terms of interfaces at least, the documentation is largely complete. XML Productivity Features Appendix • It is relatively straightforward to program with the XML API of InDesign CS, compared to programming with the APIs that manipulate native document content. It is somewhat easier to work within the logical structure of a document with tagged content than within the native document model. One often-quoted reason for using an XML-based workflow is for “cross-media publishing”. Whilst this may be attractive in principle as a means of repurposing content for different media, it is not clear how many mature workflows exist in the newspaper and magazine industry that use XML in this way. However, there is a trend of increasing use of XML within newspaper publishing. Wire-feeds are now available in XML vocabularies; NewsML [http://www.newsml.org], NITF [http://www.nitf.org], and supported by systems integrators and publishing systems vendors. Solutions based on the XML features of InDesign CS might include the following: 1. Automated production of catalogs and other publications that depend on database content that has a defined schema. Mainstream database vendors are shipping “XMLaware” databases, that are able to wrap the results of queries in XML or store XML documents to standard relational databases. 2. Variable-data publishing (VDP) systems to create personalised marketing material and other publications. Creating tagged placeholders for variable image content and tagged text ranges for variable text would take away some of the pain from implementing a VDP solution. 3. Importing content from diverse datasources (e.g. wire-feeds in NewsML, data from a relational database) that have different XML vocabularies into a uniform XML template using the XSLT support of InDesign CS. Appendix Native document model The native document model specifies how end-user documents are represented by InDesign CS. An InDesign CS document is represented by a hierarchy of persistent boss objects. The root node of a document is an instance of the boss class named kDocBoss. The end-user conceptual model of an InDesign CS document would be a hierarchy of spreads, master spreads, layers, pages, page items and so on. The underlying native document model has classes that represent spreads (kSpreadBoss), pages (kPageBoss), page items (kPageItemBoss). Key boss classes from the native document model are shown in a structural diagram entitled “Native document model, showing content items” on page 82, which indicates ownership relationships. The diagram has been decorated to indicate which of the classes in the diagram participate in the XML subsystem; with the exception of the class kDocBoss, which represents the root node of the native document model, the classes highlighted each model content items in the document, such as stories or images. XML Productivity Features 81 XML Productivity Features Appendix FIGURE 67 Native document model, showing content items Classes that can have an association with elements in logical structure are highlighted. These all represent content items. There are others not shown, this is a sample. Represents the root node of the document. The arrows indicate direction of ownership «boss class» kDocBoss «boss class» kSpreadBoss «boss class» kMasterPagesBoss «boss class» kDocumentLayerBoss «boss class» kTextStoryBoss «boss class» kDocWorkspaceBoss Spread Represents master spread «boss class» kSpreadLayerBoss «boss class» kPageBoss Owns content, guides, and pages Graphic frame Represents a flow of styled text Document layer as seen in user interface «boss class» kSplineItemBoss «boss class» Guide kGuideItemBoss Stores document-specific options «boss class» kGroupItemBoss Visual page bounds Represents a group of layout objects «boss class» kMultiColumnItemBoss «boss class» kImageItem Represents a placed image, such as a JPEG «boss class» kFrameItemBoss «boss class» kPlacedPDFItemBoss «boss class» kEPSItem Represents a placed PDF Represents a placed EPS graphic Column controller for a text frame, contains one or more column items Represents single column of text. Fundamental visual container for text Content items that can be tagged are identified by the interface IXMLReferenceData. Another view of the native document model is shown in the figure entitled “Native document model and XML-related interfaces” on page 83. 82 XML Productivity Features Appendix FIGURE 68 Native document model and XML-related interfaces Root node of document model. Has reference to the XML document element (kXMLDocumentBoss) stored in IXMLReferenceData interface. «boss class» kDocBoss IXMLReferenceData 1 ISpreadList::GetNthSpreadUID 1..* «boss class» kSpreadBoss 1 ISpread::QueryLayer 4..* «boss class» kSpreadLayerBoss The interface IXMLReferenceData links objects in the native document model to the logical structure. Document objects that are placeholders for content such as text, images can be of type kSplineItemBoss, one of many page item classes. 1 IHierarchy::GetChildUID Classes that don't have this interface can't be associated with elements in the logical structure. 0..* «boss class» kSplineItemBoss IGraphicFrameData 1 11 IHierarchy::GetChildUID IHierarchy::GetChildUID IHierarchy::GetChildUID 0..1 0..1 «boss class» kPlaceHolderItemBoss IImageItem IXMLReferenceData «boss class» kImageItem 0..1 «boss class» kMultiColumnItemBoss IXMLReferenceData ITextColumnSizer GetChildUID 1 1..* A graphic frame with unplaced content has an instance of this type as its child ITextFrame::GetTextModelUID 1 1 «boss class» kTextStoryBoss XML Productivity Features «boss class» kFrameItemBoss ITextModel IXMLReferenceData There are other types that can be children of a graphic frame; see kDrawablePageItemBoss subclasses for others 83 XML Productivity Features Appendix Backing store A backing store is a repository that stores part of the logical structure of an InDesign CS document, along with unplaced content. A backing store manages a collection of boss objects that each have the interface IIDXMLElement. When you tag a content item in the document, you create a new instance of a boss object (e.g. kTextXMLElementBoss) in a backing store that represents an element in the logical structure. The top-level persistence mechanism for the native document model (“Native document model, showing content items” on page 82) is what we call UID-based; so, each instance of the classes shown in the model, such as kSpreadBoss, would have a record number or UID (Unique Identifier) associated with it in the document’s database. UID-based objects can also store persistent boss objects that themselves do not have UIDs; this model is used for attributes, and widely within the Table and XML subsystems. We call this “container-managed persistence” (CMP) and distinguish it from the conventional UID-based persistence mechanism. The down-side of CMP in the InDesign CS API is that the container determines how its own storage is managed and there are slightly different semantics for each of the containers, e.g. storage of attributes differs from tables, which differs slightly from XML. The up-side is that the implementation is very efficient compared to UID-based persistence. A backing store (kSBOSPageBoss) is a storage container for “small boss objects”. The container (instance of kSBOSPageBoss) has a UID but the objects that it stores do not. The objects managed by the backing store have keys or “logical IDs”; see XMLReference::GetLogicalID(). 84 XML Productivity Features Appendix FIGURE 69 Backing stores Root node of the native document model 1 IStoryList::GetNthTextModelUID (numStories-1) IStoryList::GetNthUserAccessibleStoryUID «boss class» kDocBoss 1 "Small boss object store" or SBOS is the storage for the objects that represent the logical structure. The class kSBOSPageBoss is opaque to client code and has no public interfaces of use. It is included to give a concrete name to the backing store concept 1 «boss class» kTextStoryBoss owns 1 Root backing store «boss class» kTextStoryBoss owns 1 Backing store, user story 1 1 «boss class» kSBOSPageBoss 1 0..* 1 «boss class» kSBOSPageBoss 1 1 stores dtdFor docElement 1 stores 1..* 0..1 «boss class» kXMLDocumentBoss «boss class» kXMLDTDBoss 0..* «boss class» kTextXMLElementBoss Only the root backing store can contain an instance of kXMLDocumentBoss. Also, it is the place that an instance of kXMLDTDBoss would be stored. «boss class» kTextXMLElementBoss The backing store can also contain elements that represent comments (kXMLCommentBoss), processing instructions (kXMLPIBoss), i.e. something that has an IIDXMLElement interface The root element is held in the root backing store. It is the element that appears as Root in a new document. It is represented by an instance of kTextXMLElementBoss Each document has a root backing store, owned by a non-user accessible story (kTextStoryBoss). This stores the document-level information, such as any DTD associated XML Productivity Features 85 XML Productivity Features Appendix with the document (kXMLDTDBoss), and contains an instance of kXMLDocumentBoss. At first sight, it might seem odd that the class kTextStoryBoss (for storing a flow of styled text) owns the root backing store. However, the class kTextStoryBoss is responsible for managing many low-level containers for text-based content and the class kSBOSPageBoss is precisely that. In addition, each user-accessible story has its own backing store; this backing-store (kSBOSPageBoss) contains the XML elements that represent any marked-up text ranges in the story. The logical structure is distributed across the backing stores for all the stories in a document; as a consumer of the model, you do not need to be aware of this in your day-to-day activities. However, if you probe deeper into extending the model, then this may become significant. A backing store is an example of the use of container-managed persistence; an object of class kSBOSPageBoss (“Small Boss Object Store”) is responsible for maintaining a collection of boss objects that each aggregate the interface IIDXMLElement. Each kSBOSPageBoss object is owned by a boss object of class kTextStoryBoss. Root backing store and notification Even though there are multiple backing stores (kSBOSPageBoss objects) in a document, only one, the root backing store, stores an instance of kXMLDocumentBoss. The root backing store is owned by a boss object of class kTextStoryBoss that is present in every document as a non-user accessible story. This object has associations with various lowlevel boss objects, which implement the storage for the elements in the logical structure. The elements are held in a “small boss object store” (kSBOSPageBoss) owned by this kTextStoryBoss. The architecture of the backing store is largely opaque to client code and there are no public APIs of interest on kSBOSPageBoss. However, there are various facades (e.g. IXMLUtils) and helper classes (e.g. XMLReference) that encapsulate interaction with the backing store. When the logical structure of a document changes, the commands that change the logical structure notify about changes in the backing store. The subject for the change is the story that owns a particular backing store. Note that the subject for notifications about change in the logical structure is a UID-based object (instance of kTextStoryBoss). You can find a snippet of code showing the correct way to acquire of the backing store subject in the figure entitled “Code acquiring the root backing store subject” on page 86. Consult the table entitled “Low-level command notification details” on page 87 for the other information required to listen for changes in document logical structure. At some point, this information should be present in the API documentation, but currently sits off to one side. FIGURE 70 Code acquiring the root backing store subject // The XML document element lives in the root backing store InterfacePtr<IIDXMLElement> docElement(Utils<IXMLUtils>()->QueryDocElement(db)); UIDRef baseUIDRef = docElement->GetXMLReference().GetUIDRef(); // This refers to an instance of kTextStoryBoss, which is a non user-accessible // story present in every document that manages the XML information in a doc. InterfacePtr<ISubject> backingSubject(baseUIDRef, UseDefaultIID()); 86 XML Productivity Features Appendix // // // // // you need the above subject if you want to listen for changes in the document’s logical structure. For instance, the next line shows how a command to create a new element in the structure notifies: backingSubject->Change(kXMLCreateElementCmdBoss, IID_IIDXMLELEMENT, this); Low-level command notification This section provides notification details for low-level commands that are processed by the XML subsystem to allow you to observe these commands being processed, not to process them. It is recommended to check the use-cases for the wrapper methods, e.g. on IXML<whatever>Commands or IXML<whatever>, rather than trying to parameterize and process the low-level commands directly. If there are gaps in the wrapper methods, then the use-cases specify how to parameterize and process the low-level command (for instance, see “Applying a mapping” on page 50). Command output may be stored in the item-list of a command boss object on output, which is sent as the changedBy parameter in the IObserver::Update message. When implementing an observer, you can cast the changedBy parameter of the Update method to an interface pointer of type ICommand* as shown below. ICommand* iCommand = (ICommand*)changedBy; const UIDList itemList = iCommand->GetItemListReference(); When the command output shows that the output is stored in an interface on the command (e.g. as an XMLReference), then you might write code like this: InterfacePtr<IXMLReferenceData> cmdData(iCommand, UseDefaultIID());if(cmdData) { XMLReference xmlRef = cmdData->GetReference();...} TABLE 1 Low-level command notification details Boss ClassID (theChange) Subject Protocol Command output, if any kImportXMLFileCmdBoss Document (kDocBoss) into which content was imported IID_IIMPORTMANAG ER IImportFileCmdD ata::GetSysFile() stores path of file imported kXMLCreateTagCmdBoss Aggregates IXMLTagList, e.g. kDocWorkspaceBoss or kWorkspaceBoss IID_IXMLTAGLIST Item-list contains UID of kXMLTagBoss created kXMLSetTagColorCmdBoss Aggregates IXMLTagList, e.g. kDocWorkspaceBoss IID_IXMLTAGLIST Item-list contains UID of kXMLTagBoss processed kLoadTagListCmdBoss Aggregates IXMLTagList, e.g. kDocWorkspaceBoss IID_IXMLTAGLIST Item-list contains UIDs of kXMLTagBoss objects added XML Productivity Features 87 XML Productivity Features Appendix Boss ClassID (theChange) Subject Protocol Command output, if any kXMLDeleteTagCmdBoss Aggregates IXMLTagList, e.g. kDocWorkspaceBoss IID_IXMLTAGLIST Item-list contains UIDs of objects that were deleted kXMLCreateElementCmdBoss Story (kTextStoryBoss) that owns root backing store IID_IIDXMLELEMENT IXMLCreateElem entCmdData to get XMLReference kXMLDeleteElementCmdBoss, kXMLDeleteElementAndConten tCmdBoss Story (kTextStoryBoss) that owns root backing store IID_IIDXMLELEMENT IXMLDeleteEleme ntCmdData to get XMLReference kXMLMoveElementCmdBoss Story (kTextStoryBoss) that owns root backing store IID_IIDXMLELEMENT IXMLMoveEleme ntCmdData to get XMLReference kXMLPlaceElementCmdBoss Story (kTextStoryBoss) that owns root backing store IID_IIDXMLELEMENT IXMLReferenceD ata to get XMLReference kXMLMapTagToStyleCmdBoss Target workspace, aggregates IXMLTagToStyleMap IID_IXMLTAGTOSTYL EMAP kXMLUnMapTagToStyleCmdB oss Target workspace, aggregates IXMLTagToStyleMap IID_IXMLTAGTOSTYL EMAP kXMLMapStyleToTagCmdBoss Target workspace, with IXMLStyleToTagMap IID_IXMLSTYLETOTA GMAP kXMLUnMapStyleToTagCmdB oss Target workspace, with IXMLStyleToTagMap IID_IXMLSTYLETOTA GMAP kXMLCreatePICmdBoss Story (kTextStoryBoss) that owns root backing store IID_IIDXMLELEMENT IXMLCreateElem entCmdData for XMLReference kXMLCreateCommentCmdB oss Story (kTextStoryBoss) that owns root backing store IID_IIDXMLELEMENT IXMLCreateElem entCmdData for XMLReference Entities supported There are some standard entities supported by default by the XML subsystem, shown in the table “Standard entities supported” on page 89. If you need to support a wider set, for instance, the entire ISO-LATIN 1 character entities (e.g. &174; for ™, trademark), then you will find that it is possible to use them with the applications if they are defined in DTD. For instance, Simplified DocBook [http://www.oasis-open.org/docbook/xml/simple/sdocbook/] contains additional entity definitions within its DTD to support ISO-LATIN 1. 88 XML Productivity Features Appendix TABLE 2 Standard entities supported Entity Meaning Description & & Ampersand < < Less than > > Greater than ' ' Apostrophe " " Quote 
 CR Character replacement entity for carriage return 
 LF Character replacement entity for line feed Assets from XSLT example FIGURE 71 Basic grammar for article-based publications <?xml version="1.0" encoding="UTF-8"?> <!ELEMENT publication (article)+> <!ELEMENT article (article-title, body)> <!ELEMENT body (title | subhead | para)+> <!ELEMENT article-title (#PCDATA)> <!ELEMENT title (#PCDATA)> <!ELEMENT subhead (#PCDATA)> <!ELEMENT emphasis (#PCDATA)> <!ENTITY % pub.content "#PCDATA"> <!ELEMENT para (%pub.content; | emphasis)*> FIGURE 72 Fragment of XSL stylesheet to convert NITF to basic pub <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:strip-space elements="*"></xsl:strip-space> <xsl:output method="xml" omit-xml-declaration="yes"/> <xsl:template match="text()"><xsl:value-of select="normalize-space(.)"/> </xsl:template> <xsl:template match="/"> <xsl:apply-templates></xsl:apply-templates> </xsl:template> <!-- include content from these elements --> <xsl:template match="nitf|block|body.head|ul"> <xsl:apply-templates></xsl:apply-templates> </xsl:template> <!-- exclude content we are not interested in with this empty template --> <xsl:template match="*"/> <xsl:template match="body"> <article><xsl:apply-templates></xsl:apply-templates></article> </xsl:template> <xsl:template match="body.content"> XML Productivity Features 89 XML Productivity Features References <body><xsl:apply-templates></xsl:apply-templates></body> </xsl:template> <xsl:template match="p"> <para><xsl:apply-templates></xsl:apply-templates></para> <xsl:text> </xsl:text></xsl:template> <xsl:template match="hedline"> <article-title><xsl:value-of select="hl1"/></article-title><xsl:text> </xsl:text> </xsl:template> <xsl:template match="hl1"> <title><xsl:value-of select="."/></title><xsl:text> </xsl:text> </xsl:template> <xsl:template match="nitf-table"> <para><emphasis>Table omitted on import</emphasis></para><xsl:text> </xsl:text> </xsl:template> <xsl:template match="hl2"> <subhead><xsl:apply-templates></xsl:apply-templates></subhead><xsl:text> </xsl:text> </xsl:template> <xsl:template match="em"> <emphasis><xsl:apply-templates></xsl:apply-templates></emphasis> <xsl:text> </xsl:text> </xsl:template> <xsl:template match="org"> <xsl:text> </xsl:text> <emphasis><xsl:apply-templates></xsl:apply-templates></emphasis> </xsl:template> <xsl:template match="li"> <para><xsl:apply-templates></xsl:apply-templates></para> <xsl:text> </xsl:text></xsl:template> </xsl:stylesheet> References 90 • Adobe PDF Reference [http://partners.adobe.com/asn/tech/pdf/specifications.jsp] • Mobile SVG Specification [http://www.w3.org/TR/SVGMobile12/] • Walsh N, Muellner L. (1999). DocBook, The Definitive Guide. O’Reilly & Associates, Inc., CA • W3, HTML Table Model. [http://www.w3.org/TR/REC-html40/struct/tables.html] • XHTML. [http://www.w3.org/MarkUp/]