ResolveExternalLinksComponent

Introduction

ResolveExternalLinksComponent is a custom Sandcastle build component that allows you to configure ID-to-URL mappings so that you can specify hyperlinks in your MAML topics and code comments using IDs instead of actual URLs. It's also extensible and supports mappings from third-party sources, such as a proprietary web service or a database. There's even a built-in database provider that resolves IDs to hyperlinks stored in an ODBC, OLE-DB, SQL Server or Oracle database, for example.

Getting Started

As of DocProject 1.10.1 RC this component does not have to be downloaded separately; it will be added automatically to new DocProjects and DocSites. For other tools or command-line use, download the latest release: ResolveExternalLinksComponent 1.0.

Follow the instructions in the Configuration section below to configure the component. For use with other automation tools, refer to their documentation to find out how to apply the example configurations.

Dependencies

The code is based on the Hosted Visual Studio C# Item Template from the Sandcastle Build Component Templates 1.2 release, which means that the latest release of DocProject must be installed to build the source code but it does not have to be installed to use the compiled assembly with Sandcastle on the command-line or in other Sandcastle automation tools.

To build the source code the same dependencies are required as with the Hosted template; they are DocProject, BuilderAssemblerLibrary and various Framework assemblies. Refer to Sandcastle Build Component Templates for more information.

Editor

When the component is used with tools such as DocProject or Sandcastle Help File Builder it can display a graphical user interface (GUI) for editing its underlying XML configuration:

ResolveExternalLinksComponent editor with a DatabaseUrlMappingProvider selected
Figure 1: ResolveExternalLinksComponent editor with a DatabaseUrlMappingProvider selected

General Tab
Provides a user interface (UI) for configuring component-level attributes.

Namespaces Tab
Provides an editable list of XML namespaces that are used by the parser when applying the XPaths defined on the General page.

When using this component in conceptual builds, for example, the MAML namespace must be added so that <link> elements can be resolved. (See Example Configuration below.)

Mappings Tab
Provides a UI for adding, editing and deleting URL mapping providers.

Mapping providers can also provide their own editor to be hosted by this UI. For example, the DatabaseUrlMappingProvider provides an editor that allows you to specify the database Connection, Query and Parameters.

DocProject Features

When the editor is used in DocProject it will also populate the Topic ID drop-down list with all of the APIs that are available. Note that if a reflection.xml file does not exist from a previous help build then the list will remain empty.

Also in DocProject when you click the ellipses button (...) to browse for a file, the initial directory that the dialog uses will be the project's Help\Settings folder.

In the DocProject Properties window there are more properties that can be edited by expanding the component in a build component stack:

ResolveExternalLinksComponent Properties
Figure 2: ResolveExternalLinksComponent Properties

Usage

Once the component has been added to a stack you can then begin to use new attributes for <see> elements in your code comments and new attributes for <link> elements in MAML topics to reference the configured mappings.

Comments: <see xref="id"/> and <seealso xref="id"/>
MAML: <link xref="id"/>

The xref attribute requires a valid ID. If a matching ID is found in the configured mappings then the corresponding href will be used. If a matching ID is not found then the component will issue a warning and replace the reference with text only.

If a matching ID is found but no href is specified, and if no base URL is defined in scope (see Combining with a base URL below), then the component will issue a warning and replace the reference with text only.

Comments: <see vref="url"/> and <seealso vref="url"/>
MAML: <link vref="url"/>

The vref attribute uses a relative URL as an ID. If a matching ID is found in the configured mappings then the corresponding href will be used; otherwise, the ID itself will be used as the value for href.

If a matching ID is found but no href is specified then the ID itself will be used as the value for href.

Combining with a base URL
After an href has been resolved the component will attempt to combine it with the most derived base URL that is in scope.

When defined, the base URL on the <mappings> element will be combined with the href to form a complete URL. But if there's no base then the global base URL (defined on the <component> element) will be combined with the href; otherwise, the href itself will be used as the entire URL.

Examples

The following example uses the new attribute types on <see> elements in the remarks section of XML documentation comments.

<remarks>
  <p>

    See my <see xref="home"/> page.

  </p><p>

    <see xref="contact">Contact me.</see>

  </p><p>

    <see vref="/example.htm">See an example.</see>

  </p>
</remarks>

The following example uses the new attribute types on <link> elements in the content of a section area in a MAML topic.

<section>
  <title>Example links</title>
  <content>
    <para>

      See my <link xref="home"/> page.

    </para><para>

      <link xref="contact">Contact me.</link>

    </para><para>

      <link vref="/example.htm">See an example.</link>

    </para>
  </content>
</section>

With the above usage and the configuration from the XmlUrlMappingProvider example below, the following links will be created:

See my <a href="http://davesexton.com/" target="_parent">home</a> page.
<a href="http://davesexton.com/Contact/Default.aspx" target="_parent">Contact me.</a>
<a href="http://microsoft.com/example.htm" target="_blank">See an example.</a>

Configuration

To use the component you must add it to a build component stack. The process may differ depending upon the presentation style that you're using, but normally the component must be inserted after the CopyFromIndexComponent that imports XML comments and before the main TransformComponent, which usually follows immediately after.

Instructions for adding the component depend on the tool that you're using to automate Sandcastle:
  • DocProject: This component is built-in as of the 1.10.1 Release Candidate; it will automatically be included in new DocProjects and DocSites. For existing projects, see How To Use Third-Party Build Components In DocProject for instructions on how to add the component to one of the reference stacks. Also refer to this article for information on configuring the component using its built-in editor and the DocProject Properties window.
  • Command-line: Locate your presentation style's sandcastle.config file and add a new <component> element at the correct location. See the example configuration below.
  • Other tools: Refer to their documentation for instructions on how to insert custom build components.

Example Configuration

The following is an example XML configuration element for this component as it might appear in a sandcastle.config file. It also illustrates a few different types of mapping providers:

<component type="DaveSexton.Sandcastle.ResolveExternalLinksComponent"
           assembly="C:\...\DaveSexton.Sandcastle.dll"
           target="_top" base="http://microsoft.com" enabled="true">

  <!-- XmlUrlMappingProvider (default) -->
  <mappings>
    <url id="home" href="http://davesexton.com" />
    <url id="contact" href="http://davesexton.com/Contact" />
  </mappings>

  <!-- FileUrlMappingProvider -->
  <mappings file="..\..\Help\Settings\links.xml">
    Get the <url/> elements from a settings file.
    This inner XML is completely ignored.
  </mappings>

  <!-- A custom UrlMappingProvider -->
  <mappings type="SomeNamespace.CustomUrlMappingProvider" assembly="C:\...\MyAssembly.dll">
    <custom>This is configuration for the custom provider.  
            Any inner XML will do, but a custom tag is being used as an example.</custom>
  </mappings>
</component>

The following is an example XML configuration element for this component as it might appear in a conceptual.config file.

Note: The mappings elements from the example above could apply to this example as well.
<component type="DaveSexton.Sandcastle.ResolveExternalLinksComponent"
           assembly="%DocProjectPath%\bin\DaveSexton.Sandcastle.dll"
           replaceSeeAlsoLinks="False" seeXPath="//ddue:link[@xref|@vref]"
           target="_top" base="http://microsoft.com" enabled="true">
  
  <seeLinkXml>
    <externalLink xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
      <linkText>{2}</linkText>
      <linkUri>{0}</linkUri>
    </externalLink>
  </seeLinkXml>
  
  <context prefix="ddue" name="http://ddue.schemas.microsoft.com/authoring/2003/5" />
  
  <!-- Reference an external file that contains URL mappings -->
  <mappings target="_blank" file="..\..\Help\Settings\links.xml" />

</component>

Schema

This section describes the schema that is supported by the component, regardless of the mapping providers being used.

<component> Element
The <component> element supports three optional attributes and two attributes that are required by Sandcastle:
  • type: Required. Must be DaveSexton.Sandcastle.ResolveExternalLinksComponent.
  • assembly: Required. Must be the full path to the DaveSexton.Sandcastle.dll assembly.
  • enabled: Optional. Enables or disables the component. The default is true.
  • base: Optional. Specifies the default base URL. The default value is nothing.
  • target: Optional. Specifies the default target for hyperlinks. The default value is nothing.
<mappings> Element
The <mappings> element supports six optional attributes:
  • base: Specifies the base URL for the mappings that it contains. The default value is inherited from <component>.
  • target: Specifies the target for hyperlinks generated from the mappings that it contains. The default value is inherited from <component>.
  • topic: Specifies the full ID string of an API topic as it would appear in an XML documentation file. Specifying a topic ID associates the mappings with that particular topic only. The default value is nothing (default topic scope).
    • Note that mapping IDs must be unique within a topic scope; i.e., you can use the same ID multiple times as long as it's never duplicated within the same scope. The default, with no topic attribute specified, is considered to be the default topic scope.
    • Mappings defined within a topic scope:
      • do not apply to other topics and are never even considered when matching an ID.
      • take precedence over the default scope if a matching ID exists in both.
  • file: Full or relative path and name of a file that contains the group's configuration.
    • If no provider is specified then the file must be an XML file that contains a single root element (normally, <config>) and any number of child <url/> elements. (See XmlUrlMappingProvider below.)
    • If a provider is specified then the file's contents are passed to the provider as XML. At the very least a root element (normally, <config>) must be specified. The inner XML must be valid for the specified provider.
  • type: Full name of a type that derives from UrlMappingProvider. The default is XmlUrlMappingProvider (see XmlUrlMappingProvider below).
    • You can create custom providers. For example, if you would like to retrieve URL mappings from a web service then you could implement MyWebServiceUrlMappingProvider.
    • If the file attribute is also specified then the file's contents are passed to the provider as XML; otherwise, the <mappings> element and its inner XML is passed to the provider.
  • assembly: Full path and file name of the managed assembly that contains the type specified by the type attribute. The assembly attribute is required when type is specified, unless the provider is defined in DaveSexton.Sandcastle.dll.

Mapping Providers

A mapping provider parses the inner XML of a <mappings> element and returns a set of ID-to-URL mappings. The built-in providers allow you to easily configure mappings as a collection of <url/> elements or rows in the result set of a database query. You can also create a custom mappings provider by deriving a class from DaveSexton.Sandcastle.UrlMappingProvider.

XmlUrlMappingProvider

This provider parses the child <url/> elements within a <mappings/> element. It is the default provider used when no provider attribute is specified on the <mappings/> element.
Example Configuration
The following is an example XML configuration element for this component using only XmlUrlMappingProvider:

Note: This example configuration only applies to reference build component stacks. Additional markup is required to use it in conceptual stacks (see the Example Configuration above.)
<component type="DaveSexton.Sandcastle.ResolveExternalLinksComponent"
           assembly="C:\...\DaveSexton.Sandcastle.dll"
           base="http://microsoft.com" target="_parent">

  <mappings base="http://davesexton.com">
    <url id="home" />
    <url id="contact" href="/Contact/Default.aspx" />
  </mappings>

  <mappings target="_blank">
    <url id="example.htm" />
  </mappings>

  <mappings target="_blank" base="http://davesexton.com"
            topic="M:SomeNamespace.SomeType.SomeMethod(System.String)">

    <!-- Override home and contact for a specific topic only.
         Note that no information is inherited from the other mappings. -->

    <url id="home" href="/subsite/Default.aspx" />
    <url id="contact" href="/Contact/Default.aspx" /> <!-- href is the same but the target will be different -->
  </mappings>

</component>
Schema
This section describes the schema that is supported by XmlUrlMappingProvider.

<url> Element
The <url> element supports two attributes:
  • id: Required. Specifies an identifier that can be used when authoring topics to refer to the corresponding URL.
  • href: Optional. Specifies a URL that corresponds with the id.
    • If base is also specified on the parent <mappings> element then the actual URL will be the combination of base and href; otherwise, if base is specified on the <component> element, then that will be combined with href to form the complete URL. If no base attribute is found in scope then the href is used alone as the URL.

DatabaseUrlMappingProvider

This provider allows you to define ID-to-URL mappings in a database instead of the inner XML of a mappings element.

In scenarios where you already have URLs stored in a database or when you have a large number of URLs that must be shared between multiple tools, whether related to documentation or not, this provider can be used to author documentation without having to hard-code any URLs, only unique identifiers.

A custom editor that allows you to configure the provider is automatically embedded into the component's editor when the provider is used. With it you can easily specify the data provider, connection string, query, parameters and other settings all in one place.
Example T-SQL Script
The following T-SQL example creates a table in SQL Server that stores ID-to-URL mappings, grouped by topic IDs (an empty value for TopicID indicates no topic association).

This is just an example though. Any schema is supported as long as a query is configured that provides two columns: ID and HREF. The column names are not important, however, since the provider allows you to configure the result set columns that map to the ID and HREF values.

CREATE TABLE [dbo].[UrlMappings] (
  [TopicID] [nvarchar](150) NOT NULL,
  [ID] [nvarchar](300) NOT NULL,
  [HREF] [nvarchar](4000) NULL,
CONSTRAINT [PK_UrlMappings] PRIMARY KEY CLUSTERED
(
  [TopicID] ASC,
  [ID] ASC
))
Example Configuration
The following is an example XML configuration element for this component using only DatabaseUrlMappingProvider:

Note: This example configuration only applies to reference build component stacks. Additional markup is required to use it in conceptual stacks (see the Example Configuration above.)
<component type="DaveSexton.Sandcastle.ResolveExternalLinksComponent"
           assembly="C:\...\DaveSexton.Sandcastle.dll">
  <mappings type="DaveSexton.Sandcastle.DatabaseUrlMappingProvider"
            topic="M:SomeNamespace.SomeType.DocumentedMethod(System.String)">
    <connection provider="System.Data.SqlClient">
      Data Source=DEV1\SQLEXPRESS;Initial Catalog=Docs;Integrated Security=True
    </connection>
    <query>
      SELECT ID, HREF FROM UrlMappings WHERE TopicID = @TopicID;
    </query>
    <parameters>
      <parameter name="@TopicID" source="TopicID" />
    </parameters>
  </mappings>
</component>

Parameters can have hard-coded values or they can be mapped to a specific source. In the example above the value of the <mappings> element's topic attribute will be used as the value for the @TopicID parameter.
Schema
This section describes the schema that is supported by DatabaseUrlMappingProvider.

<connection> Element
The inner text of the <connection> element specifies the connection string that will be used to connect to the database.

One optional attribute is supported:
  • provider: Specifies the data provider. Any of the built-in Framework data providers are supported as well as plug-ins; e.g., System.Data.Odbc, System.Data.OleDb, System.Data.SqlClient, System.Data.Oracle. The default value is System.Data.OleDb.
<query> Element
The inner text of the <query> element specifies the command text that will be executed. Parameterized textual queries and stored procedures are supported, but only the first result set is used.

Four optional attributes are supported:
  • storedProcedure: A boolean that specifies whether the inner text is the name of a stored procedure. The default value is False.
  • idColumn: Specifies the name of the column from which the ID value is read. The default value is ID.
  • hrefColumn: Specifies the name of the column from which the HREF value is read. The default value is HREF.
  • timeout: Specifies the command timeout, in seconds. The default value may depend on the data provider.
<parameters> and <parameter> Elements
The <parameters> element contains zero or more <parameter> elements and supports no attributes.

The <parameter> element supports three attributes:
  • name: Required. Specifies the name of the parameter.
  • source: Optional. Specifies a source for the value of the parameter. The choices are: TopicID, BaseUrl, File and Target, which correspond to attributes on the parent <mappings/> element. The default value is Value, which indicates that the parameter's value should be taken from the value attribute instead of a source.
  • value: Optional. Specifies the actual string value of the parameter when the source attribute is not present or when it's set to Value.

Last edited Aug 22, 2008 at 12:39 AM by davedev, version 12

Comments

No comments yet.