Custom output based on Attributes

Topics: Developer Forum
Jun 17, 2014 at 8:49 PM
I am attempting to produce documentation that requires a bit more extra information than the default output, and I have no idea where to start looking to customize the output.

I have some interfaces that have an attribute on them that I'd like to include parts of the attribute in the documentation. My specific example is that I have contractual data defined by an interface that is returned via serialization from an call to a specific URI. The URI is part of the data in this attribute.

In the documentation, I'd like to be able to specify the URI without relying on developers keeping the XML documentation in-sync with reality. I'd also like to be able to create (I'm assuming) a content page that lists these URIs with a link to the interface that is available at that URI. What type of modification do I need to make to achieve this?

Thanks for such an awesome tool!
Jun 18, 2014 at 5:19 PM
I hate replying to my own message, but I started down what appears to be the correct path. I created a Presentation Style based on VS2013, enabled the Visibility: Attributes on Types and Members settings and that gave me access to the attributes in the reflection.xml file to work with. I found that you cannot <exclude /> or filter the attribute you are looking for or it will not be in the reflection.xml file. Once those were worked out, figuring out where and how I needed to modify the Transforms\utilities_reference.xsl file was a cakewalk.

Now I have a few follow up questions where I am truly stuck.
  1. I'd like to remove the display of attributes above the example shown in the "Syntax" section of the class/interface page while keeping it in the reflection.xml file. I cannot see where this is generated in the Presentation Style.
  2. I can't figure out how to get the Presentation Style that I built to show up as a selection in the VS2013 SFHB addin. I'd like to do this in such a way that the custom presentation file can be built, and that build output be recognized by the VS addin, if possible. For debugging, I'm using the standalone GUI which works fine.
Jun 18, 2014 at 7:28 PM
Creating a presentation style is the correct solution. Regarding the attributes in the syntax section, they are rendered by the syntax generators and there's no way to hide them. One option would be to create a build component that runs before the syntax component that extracts the attributes you are interested in documenting separately, creates custom elements for your transformations to handle, and removes the attribute elements so that the syntax components don't include them.

Presentation styles have an associated MEF component that SHFB looks for in order to add custom presentation styles. If you've installed the Visual Studio package, you'll find new project templates in the C#/Documentation and VB.NET/Documentation category for creating build components, plug-ins, and presentation styles. See the Creating a Presentation Style Component help topic for more information.

During development, you can use the standalone GUI with a test project and set the Component Path property to the location of the presentation style assembly so that it finds it. For deployment, it can be placed in one of several well-known locations that SHFB looks for custom components. See the Adding Third-Party Presentation Styles section in the Help File Category help topic.

Regarding the creating of a content page, the easiest way is probably to add a custom element to an existing conceptual topic in the project then create a build component that runs in the conceptual build step. The component would search for the custom element and replace it with one or more tables for example containing the URIs and links to the topics of the related interfaces. The component would load the reflection.xml file in the working folder to find the attributes and related interfaces.

Jul 12, 2014 at 12:59 AM

Thank you for your elegant response. I decided it would be WAY too much effort to try to remove the attributes given the work I have already invested in customization. Thus far my voyage has been pretty good, with a much larger learning curve than I expected.

That said, I am generating MAML files from a WebAPI project to document a RESTful interface and automatically adding them to the conceptual content (as a standalone outside process for now, anyway). Really cool results. Thank you for such a flexible system. Hopefully I'll be allowed to share this work on GitHub.

One question - In the custom presentation style (mirrored from your VS2013 project), I wish to add some data for a type that is referenced in an attribute. The type data is not in the /document accessible from main_sandcastle.xsl that I can Xpath my way around. I'm doing something that is probably not good to get at that data:
<xsl:variable name="myVar" select="document('..\Help\Working\reflection.xml')/reflection/apis/api/blah"/>

First, what is the correct way to do the above instead of loading the reflection.xml doc in that transform? There is a query I can use that would give me a relatively small subset of data that I'd need access to to build this table that could be added to /document, but I'm hoping there is something I missed that would get me there. Fortunately, there are only a handful of times this needs to be done.

Second, is there a way to dump the xml present in the document provided in the transform? I'm really having a hard time debugging at times, and it's nice to be able to see the data present if possible. I recall seeing something about this, but my Google-foo has failed me.

Finally, is there a way to filter out a type or namespace from the TOC and/or index without excluding it from reflection.xml? I don't care if it is linkable or searchable, but there are some classes I'd prefer not to clutter up the TOC with.

Thanks again,
Jul 12, 2014 at 6:18 PM
To add data to the document element, you need to modify the BuildAssembler configuration file. In it you will find several "Copy From Index" components that copy various data in from the reflection data to the document element. The trick is finding the right one. The comments describe what info is being copied so usually its just a matter of finding which one is copying similar information and either modifying the existing expression or adding another one to copy more information. If all else fails, adding a new "Copy From Index" component entry that gets what you need is also an option.

You can use the Display Component to dump the current document content to the console/log by adding it at one or more points in the Build Assembler configuration file. An alternative is to use the Save Component to save a copy at one or more points to a different location so that you can see what it looks like. You could also create a dummy build component project and use it to debug the BuildAssembler run within Visual Studio see the Creating a Build Component topic for more information. That would let you see the document and supporting info using the Visual Studio tools and visualizers.

You can mark them with a <tocexclude/> element in the XML comments and use the TOC Exclude plug-in to remove those items from the TOC but still leave them accessible from links within topics such as the member list pages. Bear in mind that if generating website content with the VS2013 style, the hidden topics will not contain any TOC or search elements since the plug-in that adds that info won't see them in the intermediate TOC it uses to add that info.