Documenting with Embedded XML

Feb 5, 2008 at 11:54 PM
Edited Feb 5, 2008 at 11:58 PM
I have looked over the documentation and I cannot seem to find a clean way to document XML within examples, or remarks etc. I am writing a web service and the return values are in XML format.

What I would like do, is to show some examples of the returned XML data, given a sample method call, but obviously, there is a conflict here with what I want to present and what Sandcastle needs.

Any suggestions?

Perhaps a tag which says "Ignore xml processing until closing tag", and then formatting is dictated by outer tags?
Editor
Feb 6, 2008 at 2:16 AM
Any special characters like angle brackets and ampersands within XML comments need to be encoded. For example:

<example>
<code>
&lt;FirstElement&gt;
&lt:NextElement value="1" /&gt;
&lt;/FirstElement&gt;
</code>
</example>

Using the custom build components available in the Sandcastle Help File Builder project (http://www.codeplex.com/SHFB), you can use the extended attribute "source" on the <code> tag to import code from an external file including an XML fragment. That will allow you to maintain the XML as it normally appears and will retain the necessary formatting. For example:

<example>
<code source="MyExternalFile.xml" />
</example>

If you are using SHFB, the build components are added by default and you can edit their configurations via the project settings. If you aren't using SHFB, you can download the build components alone from the same URL and integrate the CodeBlockComponent and PostTransformComponent into your sandcastle.config file to provide the same functionality manually. See the Code Block Component documentation in the SHFB help file or the included documentation files with the build component download for full details. It provides several other features such as importing specific regions, code colorization, and snippet merging too.

Eric
Feb 6, 2008 at 4:53 AM

I am using SHFB, so I will give the extended attribute method a try. I guess I am being a little lazy by not wanting to create a bunch of files, but, it is probably a better practice to use external files anyway.

Still, I would like to put in a plug for a tag which does not interpret embedded XML. ;-)


EWoodruff wrote:
Any special characters like angle brackets and ampersands within XML comments need to be encoded. For example:

<example>
<code>
&lt;FirstElement&gt;
&lt:NextElement value="1" /&gt;
&lt;/FirstElement&gt;
</code>
</example>

Using the custom build components available in the Sandcastle Help File Builder project (http://www.codeplex.com/SHFB), you can use the extended attribute "source" on the <code> tag to import code from an external file including an XML fragment. That will allow you to maintain the XML as it normally appears and will retain the necessary formatting. For example:

<example>
<code source="MyExternalFile.xml" />
</example>

If you are using SHFB, the build components are added by default and you can edit their configurations via the project settings. If you aren't using SHFB, you can download the build components alone from the same URL and integrate the CodeBlockComponent and PostTransformComponent into your sandcastle.config file to provide the same functionality manually. See the Code Block Component documentation in the SHFB help file or the included documentation files with the build component download for full details. It provides several other features such as importing specific regions, code colorization, and snippet merging too.

Eric


Feb 6, 2008 at 5:26 AM
Hi,

You can use <![CDATA[ ]] sections instead of hard-coding entities such as &lt; and &gt;. For example:

<example>
  <para>Here's an example of an invalid XML file:</para>
  <code>
<![CDATA[<?xml version="1.0" encoding="utf-8"?>
<root>
  <hello>world</hello>
  <no.closing.tag>No closing tag
  <500invalid.name>Bad name</500invalid.name>
</root>]]>
  </code>
</example>

If you're not using SHFB (i.e., if you're using the command-line or another tool) then you may want to try the <include> element, which tells the compiler to pull in documentation sections from an XML file. For an example, see this thread

The markup being pulled into the XML documentation must be valid XML, however you can use CDATA sections in the XML document, as in the example above, if you need large blocks of text with escaped XML.

- Dave
Feb 6, 2008 at 2:04 PM
davedev,

Thank you, that is exactly what I needed. I also added to the <code> tag the lang=xml attribute and it works wonderfully. Coloring and the like is all done!

Here is what I ended up doing:

/// <example>
/// <para>Running the Option function will return the following</para>
/// <code lang="xml">
/// <![CDATA[
/// <?xml version="1.0" encoding="utf-8" ?>
/// <Option>
/// <LogFile Value="C:\logs\ServiceLog.xml" />
/// </Option>
/// ]]>
/// </code>
/// </example>

And then for longer XML results, I also liked the idea of using a file. What I ended up with was:

/// <example>
/// <para>Running the Option function will return the following</para>
/// <code lang="xml" source="WebService/Help/Sample1.xml"></code>
/// </example>

Thanks again!
Feb 6, 2008 at 3:09 PM

An update for those who wish to use CDATA tags in their code

Apparently the inclusion of <!CDATA[]]> tag anywhere in the code comments causes visual studio 2005 to lock up when you type a '<' within a comment block. :-(

However, there is a hotfix for this problem and it can be found at:
https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=9646
Feb 6, 2008 at 3:52 PM
Yikes! Thanks for the tip ;)

Although, I tested it before I posted it here and it worked fine for me, but I may have pasted in the comments instead of typing them. I don't remember :|

- Dave
Feb 27, 2008 at 11:03 PM
Re: <code> tag and source attribute.
I think my issue is related if not the same as here.
The documentation and various online posts suggest that you can use something like the following to pull code from your source files to use in the documentation generated by Sandcastle. I have tried to import form both both xml and c# files.
Here is what I tried for an xml file:
/// <example>
/// Import the code from a region within the source code file
/// <code lang="xml" source="C:\Heliscope\trunk\src\Windows\HeliscopeApiDocProject\bin\Debug\Helicos.Heliscope.SystemServerAPI.xml" />
/// </example>
Here is what I tried for a cs file (including one effort to use regions)
/// <example>
/// Import the code from a region within the source code file
/// <code lang="cs" title="DocProjectFolder" source="C:\Heliscope\trunk\src\Windows\HeliscopeApiDocProject\BuildProcess.cs"/>
/// <code lang="cs" title="Relative URL" source="..\Windows\SystemServerDll\HeliscopeAPIService.cs" region="Snippet1Fault"/>
/// </example>

In both the case of the xml file and the cs file the chm documentation has the first line of text followed by a code box, including the "copy code" button, but no lines of code.

It makes me think I am not using a proper path to the file, but I would expect the full path name to work.
I am using the company provided vs2005 docproject and sandcastle installs (not SHFB) and appear to be use the sept '07 Sandcastle.

Does the source attribute work to pull in lines of code from a .cs file?
Feb 28, 2008 at 12:56 AM
Hi,

The source attribute is a Code Block Component extension, which is part of Eric Woodruff's Sandcastle Standalone Build Components download. Read the component's documentation for more information.

See How To Use Third-Party Build Components In DocProject to integrate it into a DocProject or DocSite.

Note however that the article was written for features that were added to DocProject 1.9.0 RC, so if you're using an older version of DocProject then you must add the component manually to the sandcastle.help1x.config and/or sandcastle.help2x.config files, which are located in your project's Help\Presentation\Style\Configuration\ folder.

- Dave
Mar 4, 2008 at 3:58 AM
That helps, but raises more questions than it answers. I am still totally failing to add this code block component to my project. I find that I really do not understand what to do. I think I need to paste in code in the config file for the codeblockcomponent and the posttransform component. Good enough except that the "assembly" needs to be set to an assembly containing the component and such an assembly does not exist. I am unsure how to create it.

II have the downloaded code block components, xml, gif, xsl and css files, but I have to admit I don't know what to do with them. I don't know how to get them included in the necessary assembly, point to that assemble and get the "component" added to the Vs docproject.. All of the comments and instructions seem to assume the readers knows what the process here is, I don't. i am definitely missing some essential part of the process.

I feel really dumb but I think I need a step 1, 2, 3. Download the files, do something with them, add new code to the config file, change the specified directories in the sample to the directory where the downloaded files live or where you build a dll using them or something.

Any such explicit information would be MOST helpful.

Thanks
DDewitt
Mar 4, 2008 at 5:59 AM
Hi DDewitt,

I understand that all of this can be confusing and I'm sorry that the instructions aren't clear enough for you. Unfortunately, I have not used the Code Block Component yet so I can't comment on how it should be set up, specifically, but as for DocProject, the How To... article that I mentioned in this thread does explain the process of how to add build components to your project.

Basically, you'll need to:
  1. Open the DocProject Properties window for your DocProject or DocSite.
  2. Identify the build component stack(s) that you're using to build documentation (under the Configuration category).
    1. If you're building a .chm file, then you're using a Help 1.x stack.
    2. If you're building an .HxS file, then you're using a Help 2.x stack.
    3. Identify whether the component must be added to a reference stack or a conceptual stack; one exists for each version of compiled help.
      1. I'm almost sure that the Code Block Component must be added to a reference stack; Help 1.x, Help 2.x or both depending upon your needs.
  3. Click the ellipses button (...) on the right-hand side of the stack property to open its editor.
  4. In the editor, click the add button (green plus sign).
  5. In the Add Build Components dialog, click the Browse... button.
  6. Find the assembly (.dll) that contains the Code Block Component. Click Open when you find it.
    1. This is probably something that you must download - you shouldn't have to create it yourself.
  7. If the assembly defines any valid Sandcastle build component types they will appear at the bottom of the Available list. You may have to scroll down to see them.
  8. Select the components that you want to add, such as Code Block Component by double-clicking or right-mouse click and choose Select in the context menu. Selected components will be added to the Selected list.
  9. When you are done choosing components, click OK.
  10. A dialog will open that allows you to paste in the component's XML configuration. Check the documentation for Code Block Component. When you're done, click OK. The component will be appended to the end of the stack.
    1. Note: You can edit the configuration at a later time instead.
  11. Using the up and down arrows, move the component to the proper place in the stack. Refer to the component's documentation for instructions. When you're done, click OK.
    1. Typically, the instructions will be similar to, "after Copy in comments and before TransformComponent", or something similar.
  12. Click Visual Studio's Save All button or the DocProject External UI's Save button to save the project and the build component stack.
    1. Note: Editing a build component stack configuration file directly is not recommended, if it can be avoided, since DocProject has already loaded the configuration file into memory. Changes that you make manually will be overwritten with the in-memory version of the configuration file if you save changes again that were made using the DocProject Properties window.
To verify that the component was added and to configure it using its DocProject-compatible editor or Visual Studio's XML editor:
  1. Expand the build component stack property that you just edited in the DocProject Properties window; i.e., click the plus sign before the stack's name under the Configuration category.
  2. You should see the components that you added as sub properties. If you don't then set the Configuration > Show entire build component stack option to True so that components without DocProject-compatible editors are shown as sub properties. If you still don't see the component, please report the bug to me :)
  3. Click the ellipses button (...) on the right-hand side of a component to open its editor.
    1. If the component provides a DocProject-compatible editor then it will be shown.
      1. Refer to the component's documentation for instructions.
    2. If the component does not provide a DocProject-compatible editor, then the build component stack configuration file, to which you added the component, will be opened in Visual Studio's XML editor. The component's configuration will be selected and scrolled into view.
      1. Refer to the component's documentation for information about its configuration's XML schema.
- Dave
Mar 5, 2008 at 12:10 AM
Ok, I downloaded the dll's. They weren't on our company site initially.That resolves that confusion and just goes to show that delegating work doesn't always work smoothly.

However, the instructions convince me there is still some basic fact I am missing. When I click the DocProject ellipse (we are running 1.9) I have yet to get a browser, I have yet to get an add button( green plus), and I have yet to get an add component dialogue. We have the dll's in a spearate folder. It looks like the dll's need to go to a specific place. Maybe that is the problem? Or perhaps we have a problem with our DocProject setup.

Which kinda leaves me hanging.
Mar 5, 2008 at 1:06 AM
Some success.
Turns out my GUI is not as described. There is an add button, but it is not labeled and appears as a half blue and half white blob-gear-like thingy. There also seemed to be a problem saving added components when I edited the XML configuration. It was saved everytime when I did not edit the XML.

So I am working my way through the XML now and am confident something will happen.

Thanks
Mar 5, 2008 at 1:25 AM
Edited Mar 5, 2008 at 1:31 AM
Hi,


Turns out my GUI is not as described

Sorry, I changed the icon for the add button to a green plus sign in 1.10.0 RC. That should be the only difference though.


There also seemed to be a problem saving added components when I edited the XML configuration. It was saved everytime when I did not edit the XML

I'm not sure what you mean here, but if it's a bug in the dialog then it may have been fixed already in 1.10.0 RC. You can check the Application event log for error information anyway if you feel like it.

If you're referring to editing the configuration file itself, I did mention already to either use the GUI or edit the configuration file manually, but I don't recommend doing both if you can avoid it. If you do use the GUI and then edit the configuration file manually, do not use the GUI again until the project is reloaded.

- Dave

(EDIT: Fixed broken link)
Mar 5, 2008 at 6:24 PM
OK, the process seems clear.
I am editing the config file for the components I added using DocProject.
I have added the CodeBlock Component and the PostTransform component.

I am using the file in the download (SandcastleBuilder.Components.config) as a model for my component configuration.
When I add the following:
<component id="Code Block Component" type="SandcastleBuilder.Components.CodeBlockComponent" assembly="{@SHFBFolder}SandcastleBuilder.Components.dll">

and save it (using the VS Save All), the following is what is saved:
<component id="Code Block Component">

When I build the project I do not see the component added to the config file.
Same thing happens for the PostTransform component, no assembly path is saved to the config file.

It would seem the assembly path is required, but it is not accepted.
Anyone know what is supposed to happen with the component element?

Mar 5, 2008 at 6:54 PM
(for the previous post)
Not that I think it makes a difference but, The actual assembly path entered (but apparently not saved) is
C:\Heliscope\trunk\src\ThirdPartyLibraries\Sandcastle Standalone Build Components\SandcastleBuilder.Components.dll
Editor
Mar 5, 2008 at 7:48 PM
Edited Mar 5, 2008 at 7:49 PM
SHFB handles the details of merging custom build components into its configuration file at build time. The "{@SHFBFolder}" reference is specific to SHFB and acts as a tag that gets replaced at build time with the actual path to the SHFB folder where the assembly resides by default. For non-SHFB config files, use an actual path. The same would be true for any other "{@XXXX}" references within the configuration. Replace them with a literal path or option value.

Have you tried using notepad or some other text editor to alter the file? Perhaps VS or DocProject is stripping the attributes for some reason.

Eric
Mar 6, 2008 at 12:00 AM
Hi DDewitt,


When I add the following:
<component id="Code Block Component" type="SandcastleBuilder.Components.CodeBlockComponent" assembly="{@SHFBFolder}SandcastleBuilder.Components.dll">

and save it (using the VS Save All), the following is what is saved:
<component id="Code Block Component">

I assume that you're using the default component editor by clicking the ellipses button from within a stack editor dialog, correct? (I mean, instead of editing the configuration file manually.)

The default component editor does not accept the type and assembly attributes on the <component> element since it knows what they are already - you told DocProject which component to use by loading an assembly with the Browse dialog. If you add them, they are stripped out. When you open the editor again they will be gone.

However, the attributes should have been written to the actual config file. Please verify by opening the file manually. I assume that you're editing Help\Presentation\Style\Configuration\sandcastle.help1x.config.


When I build the project I do not see the component added to the config file.
Same thing happens for the PostTransform component, no assembly path is saved to the config file.

The component isn't added during a build, it's added as soon as your changes are saved.

Again, please confirm whether you're checking the actual configuration file on disc or just using the default component editor and assuming that the attributes are not being saved properly.

- Dave
Mar 6, 2008 at 1:21 AM
I do appreciate the input. It has been quite a process (and comedy of errors) getting as far as I have.

I did try pasting in the text from notepad and it still wasn't save when I used the VS "SaveAll".

davedev's assumptions are correct.
1. I am using the default component editor by clicking the ellipses button from within a stack editor dialog
2. I select "Help 1.x build component stack {sandcastle.help1x.config}"
3. I am looking at Help\Presentation\Style\Configuration\sandcastle.help1x.config for my edits.
4. When I open the file manually nothing is saved, not even the codeblock component, much less the assembly attribute.

Which explains why nothing is changed in the build.
It appears the VS DocProject edits are not making it to the file.

I can go back to VS and \tools\options\docproject,
Activeproject,
Help 1.x build component stack {sandcastle.help1x.config}
select the ellipse
and the components are there.

Ddewitt
Mar 6, 2008 at 3:39 AM
I think I am nearly there.

I focused on why the config file wasn't showing any edits.
VS wasn't saving the file. It had to be explicitly checked out of source control and open in VS. Then the config edits got saved.

It is breaking on the path to the files right now, but I think I just need to sort out what are valid paths for DocProject and Sandcastle.

Thanks
Dennis
Mar 6, 2008 at 7:20 AM
Hi Dennis,


VS wasn't saving the file. It had to be explicitly checked out of source control and open in VS. Then the config edits got saved

Can you check the Application event log for errors please? A stack trace may help me to determine where it's failing and, if possible, I'll have DocProject check-out the file automatically to prevent this issue.

Actually, automatically checking out files was on my to-do list for a while now, but I think you're the first person to actually report an issue that depended on it.


It is breaking on the path to the files right now, but I think I just need to sort out what are valid paths for DocProject and Sandcastle.

If the component allows it, relative paths should be used to the various folders in the project. For example, to reference the Art folder you would use: ..\..\Help\Art. Look at the other components for examples.

Thanks for the feedback,
Dave
Mar 6, 2008 at 8:06 PM
Code is being pulled into my doc set!! Sweet.
This is a GREAT feature.

I did check the event log and the only logged failures were the build failures.
It appears that the DocProject save fails silently.

I made new saves without the file checked out, the save failed to save, nothing appears in the event log (that I see).

Thanks for the help guys, even when you didn't know precisely what was wrong you got me looking at the right issue.

Mar 6, 2008 at 11:03 PM
Hi Dennis,

Nice to hear that you got it working :)


I did check the event log and the only logged failures were the build failures.
It appears that the DocProject save fails silently.

What source control provider are you using? I tried to reproduce the issue with Visual Source Safe but I couldn't.

With the sandcastle.help1x.config file checked in, I opened the stack editor and added a new build component. After closing the stack editor dialog I clicked Save All in Visual Studio and got an error message box:


Error saving project: TestDocSite. Access to the path "...\sandcastle.help1x.config" is denied.

Obviously it's because the file is read-only. I also got a stack trace in the Application event log that indicated the origin of the error. Not surprisingly it was: DaveSexton.DocProject.Sandcastle.BuildComponents.SandcastleBuildComponentManager.SaveChanges().

After clicking OK on the error dialog I immediately tried Save All again and got the same error. So I checked out the config file manually and then tried Save All one last time - it saved the changes correctly.

It's not the best behavior, but it works. Is it safe to assume that you didn't get any error dialog?

I guess it's possible that I inadvertently fixed the issue in 1.10.0 RC, although I think it's unlikely. (You're using 1.9.0, right?)

- Dave
Mar 7, 2008 at 3:47 AM
Victory is sweet.
It likes like they are using source depot (I see the source depot browser in the install tree).
And, we both made it work so...

Yes, they are using 1.9.0.

Thanks again, I'll look brilliant on the next contract.
Mar 7, 2008 at 8:36 AM
Hi Dennis,

I just added an update to DocProject that will be part of 1.11.0 RC. It provides a way to automatically check-out a file before it's edited. I added the fix to SandcastleBuildComponentManager.SaveChanges() and tested it with Visual Source Safe. The result was that when I clicked Save All, Visual Studio's Checking out... dialog popped up and checked out the file immediately before the code that writes to it could execute, solving the problem.

If Source Depot is a Microsoft Source Code Control Interface (MSSCCI) provider then I believe that it should work the same way.

Here's the work item:

Source Control: Automatic Check-Out Before Writes
http://www.codeplex.com/DocProject/WorkItem/View.aspx?WorkItemId=15496

I'm going to add the same fix to various other file-write operations in DocProject as well.

In case you want to update the 1.9.0 source code yourself (How To Use The Source Code), the first change that I made was to add a new method to the DaveSexton.DocProject.IProjectItem interface:

bool CheckOut();
I then created an abstract method in ProjectItemBase and added the following implementation to VSProjectItem:

public override bool CheckOut()
{
  if (project.DTE.SourceControl.IsItemUnderSCC(Path))
    return project.DTE.SourceControl.CheckOutItem(Path);
  else
    return true;
}
Here's the DaveSexton.DocProject.MSBuild.MSBuildProjectItem implementation:

public override bool CheckOut()
{
  FileAttributes attributes = File.GetAttributes(Path);
 
  if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
    File.SetAttributes(Path, attributes & ~FileAttributes.ReadOnly);
 
  return true;
}
And finally, immediately before the using block that creates an XmlWriter in the SandcastleBuildComponentManager.SaveChanges method, I added the following code:

if (!options.Project.GetItem(configFile).CheckOut())
  throw new CheckoutException();

- Dave