0% found this document useful (0 votes)
12 views211 pages

Working With HTML Hyperlinks

The document discusses how to programmatically create a TextBlock in XAML with a Hyperlink embedded within the text. It provides a code example demonstrating how to add text and a hyperlink in between two text segments using C#. Additionally, it highlights the differences between XAML and programmatic approaches in handling spacing and text formatting.

Uploaded by

Doctor Ammooor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views211 pages

Working With HTML Hyperlinks

The document discusses how to programmatically create a TextBlock in XAML with a Hyperlink embedded within the text. It provides a code example demonstrating how to add text and a hyperlink in between two text segments using C#. Additionally, it highlights the differences between XAML and programmatic approaches in handling spacing and text formatting.

Uploaded by

Doctor Ammooor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 211

Search…

Home

PUBLIC

programmatically make textblock with hyperlink in between text


Stack Overflow

Ask Question
Tags

Users

Jobs
8
Log In Sign Up

Teams Q&A for work


Learn More

In XAML I have the following code:

<Label Width="120" Height="20" Name="label1" SnapsToDevicePixels="True"


HorizontalAlignment="Left" VerticalAlignment="Bottom">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left">
click
<Hyperlink RequestNavigate="Hyperlink_RequestNavigate"
NavigateUri="foo">here</Hyperlink>
please
</TextBlock>
</Label>

Now I'd like to get rid of the whole TextBlock XAML and add that bit programmatically. I have no trouble
creating the TextBlock, setting the Text property to 'click please' and adding a Hyperlink to
TextBlock.Content . But how do I position the Hyperlink in between 'click' and 'please'? And how do I set the
text of the hyperlink to 'here'?

I haven't got much going, so far all I got is this:

label2.Content = new TextBlock() { Text = "click please" };


//(label2.Content as TextBlock).Content does not exist?
//and even if it does.. how do I squeeze the hyperlink in between the text?

c# wpf hyperlink textblock

share improve this question


Join Stack Overflow to learn, share knowledge, and build your career.
edited Oct 25 '11 at 13:51 Email Sign Up
OR SIGN IN WITH

Google

By13:40
asked Oct 25 '11 at Facebook
using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service.

mtijn
2,552 2 21 52

do you have any code you've tried already to work with? – Adam Tuliper - MSFT Oct 25 '11 at 13:43

I added what I have but it's not much.. – mtijn Oct 25 '11 at 13:51

add a comment

1 Answer active oldest votes


14

Here's the code to add a TextBlock with a clickable link in the middle :

Run run1 = new Run("click ");


Run run2 = new Run(" Please");
Run run3 = new Run("here.");

Hyperlink hyperlink = new Hyperlink(run3)


{
NavigateUri = new Uri("http://stackoverflow.com")
};
hyperlink.RequestNavigate += new
System.Windows.Navigation.RequestNavigateEventHandler(hyperlink_RequestNavigate); //to be
implemented
textBlock1.Inlines.Clear();
textBlock1.Inlines.Add(run1);
textBlock1.Inlines.Add(hyperlink);
textBlock1.Inlines.Add(run2);

share improve this answer

edited Oct 25 '11 at 14:08

answered Oct 25 '11 at 13:49

Nasreddine
24.9k 13 60 83

almost, but this concatenates all the inlines, spacing is not preserved – mtijn Oct 25 '11 at 14:04

@mtijn I added a space after click and before Please. It should work as expected now – Nasreddine Oct 25 '11 at 14:09

I'm still left wondering though.. how come the XAML code inserted spaces automatically whereas programmatically you have
to be specific?? should I raise this as a separate question? – mtijn Oct 26 '11 at 7:12

You should raise the question as to whether you should raise this as a separate question as a separate question. –
Jordan Morris Mar 6 '13 at 8:56

add a comment

Your Answer
Post Your Answer
Post

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie
policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged c# wpf hyperlink textblock or
ask your own question.

asked 6 years, 11 months ago

viewed 14,495 times

active 6 years, 11 months ago

Linked

2
How to add a hyperlink in a TextBlock in code?

0
Add hyperlink into a string placeholder xaml

0
Show text in TextBlock in DataGrid as HhiperLink

2
WPF messages with undefined amounts of
hyperlinks

Related

5520

What is the difference between String and string in


C#?

1047

What is the difference between const and readonly?

190
Any way to make a WPF textblock selectable?

1112

How to change the href for a hyperlink using jQuery

1349

What is the difference between an abstract function


and a virtual function?

286
Automatic vertical scroll bar in WPF TextBlock?

194
Text vertical alignment in WPF TextBlock

28
Add hyperlink to textblock wpf

850
How do I make links in a TextView clickable?

-2

How do I dynamically update the text in a TextBlock


control (C# - WPF)

Hot Network Questions


Complex numbers proof with modulus argument
question

Why is Elizabeth Warren's Native American


ancestry a political issue?

Fired for third time - what to do?

Can a Druid change Druid circles?

Print a Wavy String Line-by-Line

more hot questions

question feed

STACK OVERFLOW

Questions
Jobs
Developer Jobs Directory
Salary Calculator
Help
Mobile

PRODUCTS

Teams
Talent
Engagement
Enterprise

COMPANY

About
Press
Work Here
Legal
Privacy Policy
Contact Us

STACK EXCHANGE
NETWORK

Technology
Life / Arts
Culture / Recreation
Science
Other

Blog
Facebook

Twitter

LinkedIn
site design / logo © 2018 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required. rev 2018.10.17.31922
13,734,455 members 1 917 Member 8848464

Search for articles, questions, tips

home articles quick answers discussions features community help

Articles » Languages » XML » XML/XSLT


Follow

C# and XML Source Code Documentation


Michael D Elliott, 2 Apr 2010

  4.71 (331 votes) Rate:

Demonstrates how to use C#.NET's XML source documentation to produce professional, indexed, and searchable source
documentation.

Is your email address OK? You are signed up for our newsletters but your email address is either unconfirmed, or
has not been reconfirmed in a long time. Please click here to have a confirmation email sent so we can confirm
your email address and start sending you newsletters again. Alternatively, you can update your subscriptions.

Introduction
Through many years of enterprise level software development and consulting, I became critically aware of the importance of good
source code documentation, and several years ago when I began working with the first release of Visual Studio .NET beta 1 and
found C# provided built-in support for inline XML code documentation, I was thrilled.

After forming my own professional services consulting company, it was even more important to me that my customers be able to
support, maintain and extend any software that my company produces on their behalf, and solid, thorough source documentation
is one of the steps that can be taken to assist in achieving this.

In Like every other


all releases website
of Visual we use
Studio cookies.
.NET, only By
C#using
offersour site you
built-in acknowledge
support thatXML
for inline you code
have read and understand
documentation; our Cookie
however, therePolicy,
are several
Privacy
free Policy,party
and third and add-ins
our Terms of Service.
that Learn more
can be obtained to implement the same inline source XML documentation currently offered by
C#.NET in C++, VB.NET and J#. Got it!

The good news for you non-C# developers is that Microsoft Allow
has included
cookies the same inline XML code documentation support for all
.NET languages in Visual Studio .NET 2005.
Although Visual Studio .NET provides a built-in facility to produce code documentation reports, I prefer to use the open source
NDoc tool, so I will not go into detail about how to produce .htm reports using Visual Studio, but I will demonstrate how to produce
integrated, searchable and indexed source documentation for your source by using C#, Visual Studio .NET 2003 and NDoc.

NDoc does not support version 2.0 or newer. To use the details in this article and produce source documentation from your XML
documentation in your source files, you can use the free tool that can be downloaded from http://www.stack.nl/~dimitri/doxygen/.

Article Goals

Provide an overview of the built-in C#.NET code documentation features.


Provide an overview of the most common C#.NET XML documentation tags.
Demonstrate how to produce integrated, searchable and indexed API help files with NDoc.

Please provide a rating / vote before leaving this article.

This is the only way authors get any type of credit for their work they freely share with everyone. It's sad to see articles that have
helped over 100,000 people and fewer than 200 bother to vote or provide a rating.

C# Built-in Features
There are three types of comment identifiers used to document C# source code:

Marker Example Description

Double slash // Comment Used to remark or comment a single line.

Slash asterisk /* Comment */ Used to remark or comment multiple lines.

Triple slash /// Used to add an inline XML documentation tag.


Hide Copy Code

// This is a single line remark or comment

/*
* This is line 1 of a comment block
* This is line 2 of the comment block
*/

/// <summary>
/// This is a sample summary comment
/// using the 'summary' xml tag.
/// </summary>
public void GetLoginAttempts( string userId ) { … }

C# offers several XML tags that can be placed directly within your source files to document the code, and Microsoft documents
these tags very nicely in Visual Studio .NET help files. Once the developer has documented her source using the XML tags, she can
use NDoc to produce integrated .chm files that contain the source documentation.

Although the description above and in the article may use the term 'comment', the XML tags are used to produce external source
documentation. This differs from traditional code comments in that the realized documentation can be distributed as API
(Application Programmer's Interface) documentation.
Before discussing NDoc and how to produce .chm files, let's first examine how to instrument C# source code with the XML tags and
discuss some of the available XML documentation tags in more detail.

XML Documentation Tags


The XML documentation tags are used to document classes and their high level characteristics such as constructors, finalizers,
methods, properties, fields, delegates, enums, events and other characteristics.

Visual Studio .NET recognizes the /// marker and will insert common, appropriate tags for the developer when instructed to do so.
The developer instructs Visual Studio .NET to insert these tags by typing the /// marker directly above the target characteristic. The
common tags Visual Studio will insert are: summary, param (if appropriate) and returns (if appropriate).

Figure 1 illustrates a standard method before and after the developer instructs Visual Studio to insert the XML tags by typing ///
directly above the target characteristic.

Hide Copy Code

// Figure 1

// Before:

public bool StringIsValid( string validateMe ) { … }

// After the developer types 3 slashes (///)


// above the method signature:

/// <summary>
///
/// </summary>
/// <param name="validateMe"></param>
/// <returns></returns>
public bool StringIsValid( string validateMe ) { … }

Now that you know how to prompt Visual Studio .NET to insert the XML tags, let's discuss some of the common tags and their
usage. Since the tags are XML, they need to be 'well formed'. At least in the sense you need to be sure to provide the proper
closing marker and use single or double quotes as required.

In the table below, when indications are given that clicking on links will show or display other information, I am referring to links in
the produced .chm documentation files not within Visual Studio .NET. Conversely, when I mention IntelliSense or the client, the
information will be displayed in Visual Studio .NET.

Please note, I have not covered every XML tag supported by C# and Visual Studio .NET in this article, but rather the most
commonly used tags.

Tag Usage Description

Provide a short description of the type or member.


<summary>Your
summary The text typed between the opening and closing
summary</summary>
summary tags is displayed in Visual Studio's IntelliSense
when you hover over the type.

<param
name='name'>Description. Provide a description of the related parameter.
</param>
param
The text typed between the opening and closing param
'name' must be surrounded by tags is displayed when writing the client code.
single quotes.

<returns>Description. Provide a description of what the method returns to the


returns
</returns> client.

Provide more detailed information about the type or


member that may be important to someone using the
<remarks>Your remarks. type.
remarks
</remarks>
This is a good place to document things like whether the
type is thread safe or not.

Allows you to control the format of the documentation


output by inserting or wrapping segments within
para <para>Your text.</para> paragraphs.

You will nest para tags within other tags.

Indicates a short segment of code.

You will use the c tag to draw attention to particular


c <c>Your code sample.</c>
words, phrases or code in the resulting documentation.

You will nest c tags within other tags.

Allows you to link the word to the parameter with the


same name.

The paramref tag causes the contained word to be


<paramref name="name"/> linked to the param description in the resulting
documentation.
paramref Include the closing tag, and you
must use double quotes around <param name='myParm'>Desc</param>
the "name" of the parameter. <remarks>Determines if <paramref
name=”myParm”/> is either <c>null</c> or
<c>empty</c>.</remarks>

You will find this will be one of the most often used tags.

Allows you to create a reference to any type, member,


or field that can be used within the class without causing
a compilation error (this includes .NET types and your
custom types as well).

<see cref="member"/>
One really neat integration feature with this tag is that
the references integrate directly into the Visual Studio
see Include the closing tag, and you
help system.
must use double quotes around
the linked "member".
<returns>A <see cref=”System.String”/>
containing the user's unique identifier.</returns>

When you click the link on String, you will see the actual
Microsoft documentation for the String type.

Allows you to document the type of exceptions your


member will throw.

<exception <exception cref="ArgumentException"> If


cref="member"> <paramref name="firstName"/> is
<c>empty</c>.</exception>
exception
Include the closing tag, and you
must use double quotes around When you click on the member link, you will see the
the linked "member". actual Microsoft documentation for the exception type.

It is not uncommon for your methods to use more than


one <exception> tag.

The code tag is similar to the <c> tag, but it is intended


to illustrate a true code usage example.
<code>Your code sample.
code The code tag is generally enclosed within an
</code>
<example> tag set (see below).

Use the code tag in concert with the example tag.

Provides a means to illustrate code examples.

<example>Your example. Generally an example tag set will encompass a code


example
</example> tag set.

Use the example tag in concert with the code tag.

Now that you're armed with the most common tags, let's discuss the source documentation.

Documenting your Code


Documenting source code should be a standard part of the development process. If you get in the habit of documenting your
source as you write it, you will find that you can produce fully documented code much faster than if you write code and try and go
back and instrument it with documentation at a later time. I have found, if I document the code as I write it, it takes about 50% less
time to document it than if I try and go back and document it later.

If you are not used to fully documenting your source, you will have to get used to the fact that your .cs files will be longer which will
cause you to scroll more; however, one trick that I've found is to make use of .NET's region functionality to reduce this side effect.

Although I will not address it in this article, you can write your XML documentation in an external file and use the <include> tag
to link the external file to your source. You can produce the same documentation whether your comments are in the actual source
.cs files or in an 'include' file.

I try to ensure I provide documentation for all types and their members in my source. Although the particular implementation
dictates the tags used, I try to provide at least the following XML tags for the related types (I document all members regardless of
their scope or access modifier):

Type /
Tags
Member

Classes Summary, Remarks and Example (if necessary)

Methods Summary, Remarks, Param, Returns and Exception

Summary, Value, Remarks and Exception

In the summary tag, indicate whether the property is read/write, read-only or write-only.

Properties
<summary>Gets or sets the first name of the user.<summary>

If you add this information to the summary tag, the developer will be able to see this
information in IntelliSense when they are consuming the library ... a big help.

Fields Summary

Summary and Value

Although there is a specific Value tag, indicate in the Summary tag the value of the constant,
and you will be able to see the assigned value in IntelliSense during development. I have found
Constants that this removes the need for me to go and find the constant to determine what value is
assigned because I can simply hover over the constant, and IntelliSense will do the work for me
(you gotta' try this one).

<summary>Stored procedure to access all states. Value: MyStoredProcName <summary>

Delegates Summary, Remarks, Param and Returns

Figure 2 illustrates a short class documented with all the XML tags that have been discussed in this article.

Hide Shrink Copy Code

// Figure 2

namespace Mike.Elliott.Articles.XML.Documentation
{
using System;

/// <summary>
/// The <c>DocumentationSample</c> type
/// demonstrates code comments.
/// </summary>
/// <remarks>
/// <para>
/// The <c>DocumentationSample</c> type
/// provides no real functionality;
/// however, it does provide examples of
/// using the most common, built in
/// <c>C#</c> xml documentation tags.
/// </para>
/// <para>
/// <c>DocumentationSample</c> types are not
/// safe for concurrent access by
/// multiple threads.
/// </para>
/// </remarks>
public class DocumentationSample
{
/// <summary>
/// Initializes a new instance of a
/// <c>DocumentationSample</c> type.
/// </summary>
/// <example>The following is an example of initializing a
/// <c>DocumentationSample</c> type:
/// <code>
/// // Create the type.
/// DocumentationSample ds = new DocumentationSample();
///
/// if ( null == ds )
/// return;
///
/// return ds.MyMethod( "someString" );
/// </code>
/// </example>
public DocumentationSample() { … }

/// <summary>Causes something happen.</summary>


/// <param name="someValue">
/// A <see cref="String"/> type representing a value.
/// </param>
/// <exception cref="ArgumentNullException">
/// if <paramref name="someValue"/> is <c>null</c>.
/// </exception>
/// <exception cref="ArgumentException">
/// if <paramref name="someValue"/> is <c>empty</c>.
/// </exception>
/// <returns><paramref name="someValue"/>
/// as passed in.</returns>
public string MyMethod( string someValue )
{
if ( null == someValue )
throw new ArgumentNullException( "Your message." );

if ( 0 >= someValue.Length )
throw new ArgumentException( "Your message." );

return someValue;
}
}

Now let's break down the source.

Breaking It Down
Let's look at the code snippets and the way the XML documentation is used. Each XML tag listed in the tag usage table provided
earlier in this article is covered.

Figure 3 illustrates the use of <summary>, <c>, <remarks> and <para> XML documentation tags:

Hide Copy Code


// Figure 3

/// <summary>The <c>DocumentationSample</c> type


/// demonstrates code comments.</summary>
/// <remarks>
/// <para>
/// The <c>DocumentationSample</c> type
/// provides no real functionality;
/// however, it does provide examples of
/// using the most common, built in
/// <c>C#</c> code comment xml tags.
/// </para>
/// <para><c>DocumentationSample</c> types are not
/// safe for access by concurrent threads.</para>
/// </remarks>
public class DocumentationSample { … }

Figure 4 illustrates the use of <summary>, <c>, <example> and <code> XML documentation tags:

Hide Copy Code

// Figure 4

/// <summary>
/// Initializes a new instance of a
/// <c>DocumentationSample</c> type.
/// </summary>
/// <example>The following is an example of initializing
/// an <c>DocumentationSample</c> type:
/// <code>
/// // Create the type.
/// DocumentationSample ds = new DocumentationSample;
///
/// if ( null == ds )
/// return;
///
/// return ds.DoSomething( 5 );
/// </code>
/// </example>
public DocumentationSample() { … }

Figure 5 illustrates the use of <summary>, <param>, <see>, <exception>, <paramref>, <c> and <returns> XML
documentation tags:

Hide Copy Code

// Figure 5

/// <summary>Causes something happen.</summary>


/// <param name="someValue">A <see cref="String"/>
/// type representing some value.</param>
/// <exception cref="ArgumentNullException">
/// if <paramref name="someValue"/> is <c>null</c>.
/// </exception>
/// <exception cref="ArgumentException">
/// if <paramref name="someValue"/> is <c>empty</c>.
/// </exception>
/// <returns><paramref name="someValue"/> as passed in.
/// </returns>
public string MyMethod( string someValue )
{
if ( null == someValue )
throw new ArgumentNullException( "Your message." );

if ( 0 >= someValue.Length )
throw new ArgumentException( "Your message." );

return someValue;
}

Once your source is documented, you need to generate the XML documentation file used to produce the Visual Studio .NET
documentation reports or NDoc help files.

Producing the XML Documentation File


Visual Studio .NET parses the .cs files to produce the XML documentation file; however, there are a couple of configurations and
steps we need to take to make this happen.

We must tell Visual Studio to produce the XML file, what to name the file, and where to create the file. To do this, in the Solution
Explorer, right click the project and select Properties. This will bring up the project's property pages (see figure 6).

Figure 6

In the project's property pages, select the Build option under the Configuration Properties section. There are two properties you
need to be concerned about on this page. First is the "Output Path" property which tells the compiler where to write the XML
documentation file (I typically leave the path set to the bin/Debug directory because it makes using NDoc a little easier). Next, is the
"XML Documentation File" property which will be the name of your XML documentation file (see figure 7). Click Apply and then OK
to close the project's property pages.
Figure 7

The last step in producing the XML documentation file is to build the project. Once you build the project, navigate to the directory
you set as the "Output Path" for the documentation file, and you will see the .xml file (in my case the bin/Debug directory).

If you open the XML file in a browser or Notepad, you will see that the XML documentation compiler has stripped out the XML
documentation to produce the file. This also means that you can create your own XML stylesheets (XSLT) to format the
documentation any way you want.

Hide Shrink Copy Code

<?xml version="1.0"?>
<doc>
<assembly>
<name>DocumentationSample</name>
</assembly>
<members>
<member name="T:Mike.Elliott.Articles.XML.
Documentation.DocumentationSample">
<summary>
The <c>DocumentationSample</c>
type demonstrates code comments.
</summary>
<remarks>
<para>
The <c>DocumentationSample</c> type
provides no real functionality;
however, it does provide examples of using the
most common, built in
<c>C#</c> code comment xml tags.
</para>
<para>
<c>DocumentationSample</c> types are not safe
for access by concurrent threads.
</para>
</remarks>
</member>
<member name="M:Mike.Elliott.Articles.XML.
Documentation.DocumentationSample.#ctor">
<summary>
Initializes a new instance of a
<c>DocumentationSample</c> type.
</summary>
<example>The following is an example of initializing an
<c>DocumentationSample</c> type:
<code>
// Create the type.
DocumentationSample ds = new DocumentationSample;

if ( null == ds )
return;

return ds.DoSomething( 5 );
</code>
</example>
</member>
<member name="M:Mike.Elliott.Articles.XML.
Documentation.DocumentationSample.MyMethod(System.String)">
<summary>Causes to happen.</summary>
<param name="someValue">
A <see cref="T:System.String"/> type representing some value.
</param>
<exception cref="T:System.ArgumentNullException">
if <paramref name="someValue"/> is <c>null</c>.
</exception>
<exception cref="T:System.ArgumentException">
if <paramref name="someValue"/> is <c>empty</c>.
</exception>
<returns><paramref name="someValue"/> as passed in.</returns>
</member>
</members>
</doc>

Almost There
Now that you have the XML documentation file, you are ready to build the actual help files or API documentation. For this task, we
are going to use NDoc.

NDoc is an extensible open source code documentation generation tool for .NET developers. You can download a free fully
functional copy of NDoc from SourceForge.net or NDoc (many thanks to SourceForge and the developers who contributed to the
NDoc utility).

Once NDoc is installed, open up the GUI so that we can build our long awaited help files.

Building the Help Files


There are numerous configurations you can set within NDoc that dictate the content and format of the help files. I'll only cover a
few here, but the contributing authors of NDoc did a wonderful job of documenting the options. When you click in one of the
property boxes, a description of the property is displayed at the bottom of the GUI (see figure 8).

Figure 8

First, we need to add the .NET assembly(s) we want to include in the documentation. Notice we have the option to include as many
assemblies as we want. This gives you the ability to create a fully integrated help file system for your entire system or organization. If
your organization requires all C# development to be completely documented with the XML tags, you could add the production of
the integrated help files to your standard build process.

Remember, earlier in the article I indicated that I typically leave the Visual Studio project's "Output Path" set to bin\Debug because it
made working with NDoc a little easier? Click the Add button on NDoc and navigate to the Assembly file name and select the .exe
or .dll assembly (see figure 9).
Figure 9

If you leave the "Output Path" pointing to bin\Debug, NDoc will automatically find the XML documentation file and populate the
XML Doc Filename textbox. If you have changed the "Output Path", navigate to the XML documentation file to set the XML Doc
Filename, and click OK.

Without going too deep into the NDoc properties, when validating the contents of your help files, one helpful thing you can do is
navigate NDoc's UI (user interface) to the "Show Missing Documentation" section and set each property to true. This will cause the
help files produced by NDoc to mark the missing documentation in red to indicate that the documentation type is missing. When
you are satisfied with the documentation, you can turn off these properties (see figure 10).
Figure 10

OK, let's set a few properties and build our help files. The first property we want to set is the documentation type. I really like the
MSDN format, so we'll accept it as the default.

Next, under the "Documentation Main Settings" area, we need to change the OutputDirectory. I generally create a Doc
directory under the source code project folder, and point NDoc to this location (note: NDoc will produce several files).

Lastly, change DocumentInternals and DocumentPrivates, under the Visibility section, to true.

That's it for the basic properties, so all we have to do now is build the help files and take a look at them. To build the files, click the
build icon on the toolbar or select Build from the Documentation menu. Once NDoc has completed the build process, open the
help files by clicking View Icon on the toolbar or select View from the Documentation menu (see figure 11).
Figure 11

Documenting Namespaces
Additionally, I would like to discuss how to document the namespaces to which your classes belong.

Visual Studio .NET and C# do not provide a mechanism to document namespaces because namespaces are simple, logical
containers for developers to organize and structure their code. In other words, you cannot document namespaces with the inline
XML comment tags and expect them to be properly parsed into your .xml documentation file.

There is, however, an easy way to provide a summary level description for namespaces through NDoc's GUI. If you noticed in figure
10 (two images above), you will see the Namespace Summaries button located on NDoc's GUI. When you click this button, a dialog
will appear with a drop-down box containing each namespace NDoc found within your code (see figure 12).

Figure 12

Here are the steps to add a namespace summary to your documentation:

1. Click the Namespace Summaries button to obtain the Namespace dialog.


2. Select the namespace, from the drop-down, for which you want to provide a summary description (see figure 12).
3. Add the summary you want to appear in the realized documentation.
4. Repeat steps 1 - 3 for each namespace you wish to document.
5. Save the NDoc project to ensure you do not lose the namespace information just added.

Customizing the Format of Your XML Comments


One of the neat things about the realized documentation is they are HTML files. Think about that for a minute, this means you can
use traditional HTML tags within your XML comments to achieve custom formatting. In fact, the XML tags listed in this article simply
map to HTML transformations or CSS classes. For example, when you create a bullet list in your XML comments, the result
produced by NDoc (or Visual Studio .NET's HTML reports) is the typical HTML <ul> / <li> tag pair.

Hide Copy Code

//XML Comments in the source code

/// <remarks>
/// <list type="bullet">
/// <item><b>Bold</b>, <i>Italic</i>, <b><i>Bold-Italic</i></b></item>
/// <item>Superscript - 1<sup>st</sup></item>
/// <item>Subscript - 2<sub>nd</sub></item>
/// </list>
/// </remarks>
public void HTMLCommentMethod() { ... }

Parsed, transformed and resulting comment output

Hide Copy Code

<ul type="disc">
<li><b>Bold</b>, <i>Italic</i>, <b><i>Bold-Italic</i></b></li>
<li>Superscript - 1<sup>st</sup></li>
<li>Subscript - 2<sub>nd</sub></li>
</ul>

I'm sure you can see how easy it is to add Bold, Italic and other standard HTML formatting to your documentation, and you can see
the various uses for it. Since the output is simply HTML files, there is nothing preventing us from using anchors with links to external
sites or pages, adding inline JavaScript to open new windows or even "pop up" alerts. The following code illustrates a bullet list with
Bold, Italic, an Anchor (<a>) whose onclick pops up a JavaScript alert, and an Anchor (<a>) whose onclick opens a new
window that navigates to a specific URL.

Hide Copy Code

/// <summary>
/// This method demonstrates comments using <c>HTML</c> tags
/// within the <c>XML</c> comments.
/// </summary>
/// <remarks>
/// <c>HTML tag examples:</c>
/// <list type="bullet">
/// <item><b>Bold</b>, <i>Italic</i>, <b><i>Bold-Italic</i></b></item>
/// <item>Superscript - 1<sup>st</sup></item>
/// <item>Subscript - 2<sub>nd</sub></item>
/// <item>Javascript Alert - <a href='#'
/// onclick='javascript: alert( "Wow, this is cool!" );'>Alert</a></item>
/// <item>New Window -
/// <a href="#" onclick='javascript: window.open(
/// "http://sourceforge.net/projects/ndoc/" );'>
/// New Window</a>
/// </item>
/// </list>
/// <hr>
/// Something else
/// </remarks>
public void HTMLCommentMethod() { ... }

Figure 13 displays the NDoc documentation for the above method.

One valuable use for anchors pointing to external sites would be to document research found on the internet that solved certain
problems within your project or code. As an example, you could add a link to a site that documents a fix you implemented for a
known security issue.

Tips
To wrap up the article, I want to point out a few things that will make the C# XML documentation and NDoc integration really neat.
A couple of things I particularly like about the produced help files are that they are in a standard .chm format and they provide the
standard contents, index and search capability.

Also, notice that, if you had selected MSDN as the documentation type, your help files will be integrated with the .NET Framework's
help files. Notice in figure 11, the DocumentationSample class derives from System.Object, and if you click the
System.Object link, you will be taken to the .NET Framework's System.Object documentation (if you had installed the MSDN
help files during your Visual Studio .NET installation).

Have you ever downloaded an open source .NET assembly that provided poor or no documentation? If the assembly was written in
C#, and the developer used XML documentation tags, you can produce the API documentation yourself (I did this with the
Microsoft.Web.UI.WebControls assembly which proved to be very helpful).

In Visual Studio .NET, once you configure your .NET project to produce an XML documentation file and if you build the project, you
may see several warnings informing you of undocumented characteristics. Many a times you will have to use Rebuild instead of
Build to get the XML file updated properly.
Once I have validated the documentation, I will typically save the NDoc project and add the .ndoc project file to my solution and
place it in source control along with the source (note, I only have the .ndoc project file and not all the produced files as they are
very easy to recreate).

Summary
By using the C# inline XML documentation tags and NDoc, you can create comprehensive API documentation for your source. By
adding several assemblies to the same NDoc project and integrating with the .NET Framework help files, you can truly produce a
professional set of source documentation of which anyone would be proud of.

History
1.0.0.0

Initial article release

1.1.0.0

Added section on documenting namespaces

1.2.0.0

Updated Documenting Namespaces section

2.0.0.0

Added the Customizing the Format of Your XML Comments section

License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share
TWITTER FACEBOOK

About the Author


Michael D Elliott
Chief Technology Officer Craftlogic Software Follow
United States this Member

Michael is a Principal Consultant with Craftlogic Software, a technical staffing, consulting,


project outsourcing, and software development company.
At Craftlogic, we are owned and operated by technology experts and insist upon quality in all
that we do. The name, Craftlogic, is itself a reflection of our philosophy because software, we
believe, is "crafted" by skilled individuals; craftsmen.

Michael has spent almost 2 decades in the Enterprise IT industry. Michael continues to be
hands-on and involved in low level details of technologies, and he loves to guide and help his
clients achieve success.

You may also be interested in...


TridentOpt: A Multi-Objective Optimization Engine or Solver

Introducing SimpleSamSettings

Comments and Discussions

Add a Comment or Question Email Alerts Search Comments

Spacing Relaxed
Relaxed   Layout Normal
Normal   Per page 25
25     Update

First Prev Next

How to include independent general purpose reference notes? Member 4291906 26-Jul-18 16:36

C plus 1-Sep-15 11:33

Maybe add some links to documentation generators Barry Jones 12-Nov-14 15:13

My vote of 4 fatbat6288 12-Aug-13 20:21


A small observation MaliceIRL 26-Nov-12 12:27

My vote of 5 musicm122 14-Nov-12 22:55

Re: My vote of 5 Michael D Elliott 15-Nov-12 18:07

How to add a new line in the comments? Superman1001 10-Oct-12 11:05

Re: How to add a new line in the comments? Michaël Polla 17-Feb-15 14:48

Commercial product option for C# .NET Documentation Richard Slogget 5-Oct-12 20:14

Problem with example dhsc 9-Jun-12 7:23

Re: Problem with example Septimus Hedgehog 9-Jun-12 21:54

Re: Problem with example elp87 23-Oct-13 15:49

Triple slash and VC++ 2010 - doesn't work? 23741 11-Mar-12 20:55

My vote of 4 Silver0ne 5-Apr-11 15:51

Re: My vote of 4 Silver0ne 5-Apr-11 15:53

My vote of 5 Prototypjack 1-Sep-10 14:33

AtomineerUtils to auto-generate and update the XML comments Zot Williams 20-Aug-10 0:01

Alternative to NDoc Barry Jones 27-Jul-10 14:05

please avoid meaningless documentation Mr.PoorEnglish 7-Apr-10 15:59

Re: please avoid meaningless documentation ScottPlante 26-Apr-10 21:51

Re: please avoid meaningless documentation Michael D Elliott 26-Apr-10 22:47

Re: please avoid meaningless documentation Mr.PoorEnglish 27-Apr-10 0:40

Re: please avoid meaningless documentation Silver0ne 5-Apr-11 16:14

Re: please avoid meaningless documentation Mark F. 29-May-11 20:01

Last Visit: 17-Oct-18 21:42 Last Update: 18-Oct-18 11:03 Refresh 1 2 3 4 5 6 Next »

General    News    Suggestion    Question    Bug    Answer    Joke    Praise    Rant    Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile Article Copyright 2005 by Michael D Elliott
Select Language ​ ▼
Web01-2016 | 2.8.180920.1 | Last Updated 2 Apr 2010 Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid
13,734,455 members 1 917 Member 8848464

Search for articles, questions, tips

home articles quick answers discussions features community help

Articles » Third Party Products » Reviews on Third Party Products and Tools » Community Reviews
Follow

Creating PDF documents with iTextSharp


Thomas Michael Koch, 2 Nov 2011

  4.92 (42 votes) Rate:

Creating PDF documents with iTextSharp using a combination of images and text.

Is your email address OK? You are signed up for our newsletters but your email address is either unconfirmed, or
has not been reconfirmed in a long time. Please click here to have a confirmation email sent so we can confirm
your email address and start sending you newsletters again. Alternatively, you can update your subscriptions.

Download demo project - 1.65 MB

Introduction
This article is about using iText to generate PDF files using a combination of images and dynamic text written on select locations on
the image. The example project uses an ASP.NET MVC3 application to demonstrate the code but it should not be difficult to adapt
it to your own needs.

Background
Like every other website we use cookies. By using our site you acknowledge that you have read and understand our Cookie Policy,
Privacy Policy, and our Terms of Service. Learn more
Me and some friends have been running a hobby web-site called malleus.dk dedicated to two role-playing games called
Warhammer Fantasy and Dark Heresy. Got it!

One of the applications on our site is a "character generator"Allow


where users can build, configure, and maintain their role-playing
cookies
characters. We wanted to expand this tool with a print functionality allowing our users to have their characters printed to a nice
looking character sheet.

We decided that we really needed to generate a PDF document. PDF documents are supported in all browsers and seems to be the
de-facto standard for documents on the web. There are a lot of PDF components available on the net, but we quickly settled on
iText as it is a very mature product.

iText comes with a free option under the GNU Affero Public License, or with a commercial option which gives you more freedom. I
encourage you to check out the details at http://itextpdf.com/.

Using the example solution


The example solution contains two projects - a Class Library and an ASP.NET MVC application. iText is used from the Class Library,
and the web application is used for testing the Class Library.

The example creates a "diploma" for a bicycle race. You can enter name, date, the name of the race, and the distance. The web
application will produce a diploma with the entered text on top.

The basic flow of the example application is illustrated with images in figure 1, 2, and 3:

Figure 1 - The background image


Figure 2 - Entering data in example app

Clicking "Generate" will create a new PDF document:


s
Figure 3 - The resulting diploma

From here on, it is only a matter of adding more artwork, tweaking texts, fonts, etc.

Even though the diploma application is very basic, it contains all the programmatic elements required for producing output that
looks like figure 4. The artistic skill that goes into images and layout is a job for a designer.

Figure 4 - Character sheet in PDF generated using iText

Installing and setting up


Go to http://itextpdf.com/download.php and click "Download iTextSharp". In your Visual Studio project, you need to reference the
itextsharp.dll that you just downloaded.

Document generation strategy


When you open up iText and begin examining the API, you will notice that it is capable of writing text, drawing figures, inserting
images, creating PDF forms, etc.. For our task, we decided to use a combination of image fragments and text. The bottom layer will
contain all the image fragments and the top layer will contain the text.

Creating a PDF document


When you create PDF documents in iText, the top-level abstraction is the Document class. It provides various document level
information such as title, page count, etc.:

Hide Copy Code

public void Create (Stream output) {


Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, output);
document.Open();

The output stream is just a MemoryStream which is returned as a FileContentResult:

Hide Copy Code

[HttpPost]
public FileContentResult Generate(GenerateModel m) {
DiplomaPrinter printer =
new DiplomaPrinter(m.Name, m.Distance, m.Date, m.RaceName, m.ShowRulers);
MemoryStream memoryStream = new MemoryStream();
printer.Create(memoryStream);

return File(memoryStream.GetBuffer(), "application/pdf", "diploma.pdf");


}

When this controller action is invoked, it will send the contents of the MemoryStream back to the client as a PDF file called
"diploma.pdf".

To actually fill the document with content, you need to learn to use the PdfWriter, PdfReader, and PdfTemplate classes.

Bottom layer
The bottom layer of the page is filled with other PDF fragments and images. Figure 2 contains our background image. To load
these elements into the document, you do the following:

1. Load the PDF fragment using a PdfReader.


2. Use the reader to create a PdfTemplate instance.
3. Add the PdfTemplate to your current Document instance.

Hide Copy Code

PdfReader readerBicycle = new PdfReader(Resources.GetBicycle());


PdfTemplate background = writer.GetImportedPage(readerBicycle, 1);

Create a new page in the document and add the PdfTemplate instance to it:

Hide Copy Code

document.NewPage();
PdfContentByte pcb = writer.DirectContentUnder;
pcb.AddTemplate(background, 0, 0);

Resource.GetBicycle() simply returns a Stream instance to a resource embedded within the assembly. The call to
document.NewPage() generates a new page in the Document instance and the writer.DirectContentUnder property
returns a PdfContentByte instance for the bottom layer of this new page. The pcb.AddTemplate() invocation adds the
loaded PDF fragment to the document and positions it on the bottom left corner - coordinates x = 0 and y = 0.

At first it seems odd that you have to use the PdfWriter instance to transform the contents of the PdfReader into a
PdfTemplate. As Bruno Lowagie - the creator of iText - explained to me, this is done to ensure that shared objects are reused.
For instance, if you embed your own fonts in the document, the best option is to reuse this font whenever you write some text.

For more specific details, I encourage you to get a hold of the book "iText in Action - 2nd edition".

Top layer
The top layer is where I put the text. As with everything else in iText, you have several options. You can add entire paragraph
objects or print text at specific points. Since I need to print on top of an image/PDF fragment, I went with the last option.

Hide Copy Code

PdfContentByte pcb = writer.DirectContent;


pcb.BeginText();
SetFont36();
PrintTextCentered(_raceName, 280, 680);
PrintTextCentered(_name, 280, 190);

SetFont18();
PrintTextCentered(_date, 280, 640);
PrintTextCentered("has completed a distance of " + _distance, 280, 160);

_pcb.EndText();
writer.Flush();

The numbers in this code fragment represent a position in a coordinate system.

Setting the font and size:

Hide Copy Code

private static readonly BaseFont font =


BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, false);

private void SetFont36() {


_pcb.SetFontAndSize(font, 36);
}

Invoking this method will set the font to Helvetica with size 36. This will affect the invocations to the following method:

Hide Copy Code

private void PrintTextCentered(string text, int x, int y) {


_pcb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, text, x, y, 0);
}

The _name, _distance etc. fields are injected into the DiplomaPrinter class via the constructor.

Closing the document


To end the document, you should flush your writer and call Close on the document:
Hide Copy Code

writer.Flush();
document.Close();

This has the effect of pushing the PDF document down to the output stream that you used to create the document with in the first
place.

Tricks
When generating documents this way, you often need to adjust the position of text and images. To help with this, I created two
methods for adding a ruler to the generated PDF document. If you check the "add rulers" box in the example application, you
should see something like the following:
Figure 5 - Diploma with rulers

Having these rulers makes it much easier to find the positions of text and images.

You can also play around with the code-page being used by iText when generating text. This is done by changing the value of the
encoding parameter of the BaseFont.CreateFont() method. The example uses the value "Cp1252" which is for Western
Europe. Reading the source code for iText, I can see that it also supports the values "Cp1250" (Central- and Eastern Europe) and
"Cp1257" (the three Baltic states) but I have yet to play around with these.

Conclusion
iText is a mature piece of software with tons of possibilities. I have only scratched the surface of what is possible. A quick scan of the
API reveals that you can do PDF forms, drawing, encryption, etc. I once tried to read the PDF specification and found that it is one
complex beast. I very much prefer delegating the work to an API such as iText.

History
1 November 2011 - First edition.

License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share
TWITTER FACEBOOK

About the Author


Thomas Michael Koch
Software Developer (Senior) Follow
Denmark this Member

No Biography provided

You may also be interested in...


Pro Using PDFs to Manage and Share TridentOpt: A Multi-Objective
Content Optimization Engine or Solver
E-signing PDF documents with Introducing SimpleSamSettings
iTextSharp

Creating PDF Documents in ASP.NET ITextSharp Helper Class

Comments and Discussions

Add a Comment or Question Email Alerts Search Comments

Spacing Relaxed
Relaxed   Layout Normal
Normal   Per page 25
25     Update

First Prev Next

Thank you! Jessyka Lage 8-Oct-18 23:07

insert codebar base64 itextsharp pdf juceboper 6-Dec-17 19:35

Quality is lower in production (older operating system) ksyinc2451 20-Feb-14 21:35

My vote of 5 Renju Vinod 29-Oct-13 6:54

Code breaks on 5.4.2 alpinescrambler 22-Jul-13 19:31

My vote of 5 Eric Willingham 27-Feb-13 15:37

Adding fields with custom font 6-Feb-13 11:05

How to show special characters č or ć in pdf AlmirM 26-Nov-12 21:57

How to do the same with a web form ameshlalvr 2-Jul-12 9:53

Re: How to do the same with a web form ameshlalvr 3-Jul-12 10:15

Re: How to do the same with a web form ameshlalvr 3-Jul-12 10:59

Re: How to do the same with a web form Thomas Michael Koch 3-Jul-12 22:15
Re: How to do the same with a web form ameshlalvr 5-Jul-12 12:41

Can you point me to reference materials to help me incorporate the conacher 1-Dec-11 22:35
solution into an MFC application?

Re: Can you point me to reference materials to help me incorporate the Thomas Michael Koch 2-Dec-11 2:23
solution into an MFC application?

Re: Can you point me to reference materials to help me incorporate Member 3455398 14-Jan-12 0:40
the solution into an MFC application?

Webform KentACar 8-Nov-11 16:53

Re: Webform Thomas Michael Koch 8-Nov-11 22:12

Re: Webform KentACar 9-Nov-11 0:56

My vote of 5 blowagie 5-Nov-11 18:36

Last Visit: 17-Oct-18 21:42 Last Update: 18-Oct-18 11:06 Refresh 1

General    News    Suggestion    Question    Bug    Answer    Joke    Praise    Rant    Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile Article Copyright 2011 by Thomas Michael Koch
Select Language ​ ▼
Web06-2016 | 2.8.180920.1 | Last Updated 2 Nov 2011 Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid
Tech · 29 May 2012 · 5 min read

Developing an extended
Drag And Drop TreeView
control in C# .Net

Rolf Baxter

This blog pos talks about developing an extended Drag and Drop TreeView control in C#. I say extended because
the .Net framework already provides simple drag and drop functionality, but the visual feedback during the drag
operation is somewhat lacking. I found a number of TreeView extensions on CodeProject, some of which work
quite nicely. However, people have tended to focus on moving folder sructures in 'Windows Explorer' type clones,
while I wanted to focus on resructuring generic trees. In that spirit, this control shows the subsructure of the data
you are moving during the drag operation, as opposed to a moving folder image.

Overview
Until recently I had never really used the drag and drop functionality of the .Net framework so wanted to
experiment a little. In pondering the 'time and the place' to use drag and drop I found an interesing article by Leisa
Reichelt (here). Her research suggesed that users generally preferred to use drag and drop during data
manipulation problems such as organising items relative to each other. Indeed, mos of us have made extensive
use of drag and drop in Windows Explorer to move fles around, and thus the .Net TreeView control seemed like
an excellent tes subject on which I could experiment.

Given the prominence of drag and drop within windows I was somewhat surprised to fnd that the .Net
Framework's TreeView control supplied only basic drag and drop provisions, and having quickly grown bored of
this functionality extending the control became the object of my experimentation. Where the control particularly
lacks provision is in re-sructuring a tree within a control, which you simply cannot do. Furthermore, although you
can drag data from one control to another using the Drag and Drop API, the visual feedback is severely limited and
fails to communicate what datais being dragged. It was these two aspects in particular that I focused on during my
experimentation. In this pos I'll talk about a couple of interesing elements of my experience, while the full control
and sample application is available here.

To illusrate the end result, Figure 1 shows Branch 0 - Sub-branch 1 as it is dragged into Branch 1, and we can
show the same feedback when dragging from one control to another to replace the disinctly unimpressive
feedback given by sandard Drag and Drop.

Displaying the dragged data & dragging between controls


While experimenting with various ways of showing the data being dragged, I decided that using a borderless form
with a partial treeview provided a simple but efective solution. The extended TreeView uses a member variable to
keep track of the TreeNode being dragged, so building a second TreeView to illusrate its sructure in a popup is
trivial.

For dragging between controls you can hook into the sandard drag and drop API. The great thing about this is that
by lisening to the DragEnter event we can directly access the data being dragged (the TreeNode), so it is simple
to initialise a new popup window when our control's DragEnter event fres. The resulting event handler looks as
follows:

private void OnDragEnter(object sender,


System.Windows.Forms.DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(TreeNode)))
{
e.Effect = DragDropEffects.Move;
TreeNode tn =
(TreeNode)e.Data.GetData(typeof(TreeNode).FullName, true);
if (!CompareNodeTagState(_nodeBeingMoved, tn))
{
_nodeBeingMoved = tn;
ReInitMovingDataWindow(_nodeBeingMoved);
}
// We have some valid data in _previousSelectedNode,
// so change the curser back
this.TopLevelControl.Cursor = Cursors.Default;
this.Focus();
}
else
{
e.Effect = DragDropEffects.None;
_nodeBeingMoved = null;
}
}

The other great thing about hooking into the drag and drop API is that it exposes the actual objects being moved
rather than a serialised copy. This means that when it comes time to change the TreeNode's parent, we jus call
TreeNode.Remove() and then add the node to its new parent. This automatically removes the node from the
source control (where the drag sarted) and leads to a very neat solution.

Node Highlighting
One of the other things I wanted to do was to use node highlighting to identify resructured tree components. The
fgure above shows that the data being dragged is highlighted blue in addition to the popup window. Furthermore,
once the data is dropped into a new location the data is highlighted green. One can allow the user to resructure
the data through multiple drag and drop operations by persising sate information until a save operation is called.

I chose to persis sate information by using the TreeNode Tag property to hold a simple NodeState sructure, and
the helper function 'GetNodeTagState' was useful for accessing a TreeNode's sate. These are shown below:

struct NodeState
{
Public bool Moving;
Public bool Moved;
public int Id;
};

...

private static NodeState GetNodeTagState(TreeNode node)


{
if (node == null)
{
throw new Exception("Cannot get tag state from null node");
}

NodeState state;
if (node.Tag != null) state = (NodeState)node.Tag;
else
{
state = new NodeState();
state.Id = node.GetHashCode();
}
return state;
}

The sates of TreeNodes are primarily manipulated during the ItemDrag and DragDrop event handlers, and
similarly, TreeNode BackColor is driven from the TreeNode tag sate in similar locations. One could add in further
events to automatically change the TreeNode BackColor whenever the node's sate changes, although I have not
done this in the example code.

Auto-scrolling during drag


Another interesing aspect I invesigated was how to enable auto-scrolling when the cursor is near the top or
bottom of the tree during a drag operation. This task is made slightly more challenging by the fact that the cursor
may be over another control (not the source).

This problem was solved by identifying the control under the mouse during the OnGiveFeedback event, and using
a timer to auto-scroll that control while the cursor remained near its border. To identify the control under the cursor
we can use the GetChildAtPoint method, as shown below:

Point topLevelPoint = this.TopLevelControl.PointToClient(Control.MousePosition);


Control ctl = this.TopLevelControl.GetChildAtPoint(topLevelPoint);

if (ctl != null &amp;&amp; ctl.GetType().FullName.Equals(this.GetType().FullName) &amp;&amp;


ctl.AllowDrop)
{
_controlUnderMouse = ctl;
}

Once we have the control, checking if the cursor is near its edge can be done as follows (a
_controlBorderTollerance of 30 pixels seemed to work well):

Point controlPoint = _controlUnderMouse.PointToClient(Control.MousePosition);


PositionByBorder nearEdge = LocationNearControlEdge(_controlUnderMouse, controlPoint.Y,
_controlBorderTollerance);

...

public static PositionByBorder LocationNearControlEdge(Control control, int y, int tollerance)


{
int width = control.Width;
int height = control.Height;

if (Math.Abs(0 - y) &lt; tollerance) return PositionByBorder.Top;


if (Math.Abs(height - y) &lt; tollerance) return PositionByBorder.Bottom;

return PositionByBorder.None;
}
To actually send a scroll reques the SendMessage interface from the Windows API is available. To use this we
need to defne the following member variables:

private const int WM_VSCROLL = 0x115;


private const int SB_LINEDOWN = 1;
private const int SB_LINEUP = 0;

[DllImport("user32.dll", CharSet = CharSet.Auto)]


private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam,IntPtr lParam);

And fnally, within the timer scroll up event (the timer runs whenever the cursor is near the control's border) we
simply call:

SendMessage(_controlUnderMouse.Handle, WM_VSCROLL, (IntPtr)SB_LINEUP, IntPtr.Zero);

N.B. Use SB_LINEDOWN in the scroll down tick event.

To keep this pos brief I'll leave the discussion of the details there, but feel free to browse and re-use the full
source code and tes application here.

Read more
View more by Rolf Baxter

View all Tech articles

Contact Us

© Copyright Scott Logic 2018. Privacy


13,734,434 members 1 919 Member 8848464

Search for articles, questions, tips

home articles quick answers discussions features community help

Articles » General Programming » WinHelp / HTMLHelp » HTML Help


Follow

Documention with DocBook on Win32


Jim Crafton, 4 Oct 2003

  4.92 (46 votes) Rate:

Writing and producing documentation (HTML Help) with DocBook

Is your email address OK? You are signed up for our newsletters but your email address is either unconfirmed, or
has not been reconfirmed in a long time. Please click here to have a confirmation email sent so we can confirm
your email address and start sending you newsletters again. Alternatively, you can update your subscriptions.

Download source files - 5 Kb


Download demo project - 9 Kb

<!-- Add the rest of your HTML here -->

Introduction
This article will cover a number of topics, but it's main point is to show you how to get up an running with producing
documentation using the DocBook help processor, and then creating customizations for producing plain html file for use on the
web or offline, or in making a single Microsoft HTML Help file (.chm) for windows. By the end of the article I'll show you how to
create and process
Like every your own
other website DocBook
we use cookies.file(s), customize
By using the style
our site you sheets for
acknowledge thatit'syou
output, and and
have read create a simple our
understand makefile
CookietoPolicy,
run the
whole thing from a command line. The article will
Privacy Policy, and our Terms of Service. Learn more mention a number of technologies, and my aim is not to explain in detail how
they work, but mainly explain how to use them to create html based documentation for Win32 (though much of this is generic to
Got it!
pretty much any OS that can run the various DocBook tools) systems. This is based on my experiences with DocBook in using it to
produce the documentation for my VCF project that I spend Allow muchcookies
of my time on.
DocBook is a very cool XML-based syntax that allows you to author documentation in a single format, and then run it through
various processors to create your final documentation output. From a single DocBook source you can output html, PDF, latex, rtf,
and many other formats. We'll focus on dealing with html and HTML Help. Once you have written your DocBook files you have a
choice in how they are processed. The original way was through a DSSSL processor such as Jade or OpenJade. DSSSL has a lisp like
syntax and is a bit unwieldy to use. The other way, and the one apparently most people use, is XSL style sheets run through an xsl
processor, like xsltproc. You can use other processors for XSL but many of them will not work correctly, and xsltproc is nice because
it doesn't require a Java runtime to be installed. I found this out the hard way after spending the better part of a day downloading
and trying several different XSL processors!

One of the many neat things about DocBook, is that from the single, plain text source, the customization style sheets can
automatically produce index, table of contents, and all sorts of extra stuff, all without you having to put much effort into it in terms
of extra writing in your documentation.

Before we do anything though, we are going to have to get some tools set up. When working with DocBook on Windows, half the
hassle is getting the tools and your environment set up right. So, first get the following tools:

Cygwin - this is free tool that provides a whole slew of command line tools that are typical with *nix systems. Cygwin is,
simply put, and awesome collection of tools for doing command line work - I can't imagine working without it. Some of the
tools included (in no particular order) are ssh, cvs, gcc, make, touch, scp, more, less, cat, bash, perl, python, and many, many
others. The setup is trivial to do (you will need be online though), and allows you to pick and choose exactly what you want.
For our purposes make sure you have at least the following selected:

bash (this the shell you use in *nix, and will let you run all sort of cool shell scripts)
make (or gmake)
libxslt (this should also install the xsltproc program)
sed
tar
gzip
find

One note: when you come to the "Select Install Directory" page make sure to click on the "DOS" choice for Default Text Type
(trust me, this will save you a lot of headaches later on).

Most of these will come with the default Cygwin installer's selection of tools. The one's to watch for are libxslt and sed. If you
miss something, you can always run the installer again and select the missing programs.

DocBook - Next you need the DocBook XSL style sheets, you get them at the SourceForge website. Look for the file labeled
docbook-xsl-1.60.1.zip (in the docbook-xsl files section). Once you've downloaded these, unzip them anywhere you want.

Microsoft's HTML Help Workshop will allow you to edit and compile HTML Help chm files, both from the GUI tool as well as a
command line program. We'll be using the command line version (hhc.exe) of the tool in this article.

Now open up your bash command line and type (you can do this via Start > Programs > Cygwin > Cygwin Bash Shell):

Hide Copy Code

xsltproc -version

You should get:

Hide Copy Code

$ xsltproc -version
Using libxml 20423, libxslt 10013 and libexslt 705
xsltproc was compiled against libxml 20417, libxslt 10013 and libexslt 705
libxslt 10013 was compiled against libxml 20417
libexslt 705 was compiled against libxml 20417

Or something similar. If you don't get this and instead see an error message you may have to go and get the libxslt package - see
above about notes on the Cygwin installer.

Now we can write a simple test. Create a file called simple.xml and copy and paste the following into it:

Hide Shrink Copy Code

<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" >

<book>
<title>Simple Book</title>
<titleabbrev>Simple</titleabbrev>

<preface><title>Introduction</title>
<para>
Hello! Here's an introduction!
</para>
</preface>

<chapter><title>On Foo's</title>
<para>
Stuff about Foo's goes here.
</para>
</chapter>

<chapter><title>On Bars's</title>
<para>
Stuff about Bars's goes here.
</para>
</chapter>
</book>

This is a simple example that create a basic unit, a "book", and adds a title, preface, and two chapters. Your basic building blocks in
terms of organizing the various sections are a book, a chapter, and a section. Chapters can nest under a book, and sections can
nest under a chapter or another section. Paragraphs are wrapped with the <para> tags and can occur most anywhere you want.

To produce our html lets run this file through our XSL processor. To use the xsltproc program, you pass it the file name of an XSL
style sheet to use, and a file name of the XML file to process. The file that gets processed must be a valid XML file, if not xsltproc will
whine and complain and will not process it. Specifically, you must have the <?xml version="1.0"?> right at the top of the
file, otherwise you'll scratch your head and curse fluently at your machine for not processing your perfectly valid XML file. Also when
passing in file names, make sure to use the "/" and not the "\" - failure to so this will cause xsltproc to trip up and not work correctly.

So lets type (assuming your DocBook XSL files are in the d:\docbook-xsl-1.60.1 directory ):

Hide Copy Code

xsltproc --nonet D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl simple.xml

Running this will produce output like this

Hide Copy Code

$ xsltproc --nonet D:/dork/DocBook/xsl/htmlhelp/htmlhelp.xsl simple.xml


Attempt to load network entity http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd
Writing pr01.html for preface
Writing ch01.html for chapter
Writing ch02.html for chapter
Writing index.html for book
Writing htmlhelp.hhp
Writing toc.hhc

Now you can open up index.html in a browser and view your documentation!

The --nonet option tells xsltproc to not attempt to connect via the network and attempt to verify the DTD. I use this so I don't have
to fight with producing documentation when I don't have a valid or reasonable fast network connection. For other kinds of XSL
processing this may be an issue, but for DocBook processing --nonet seems to work just fine.

The first thing you may want to do is break up your documentation into multiple files, as a single file may not be the easiest thing to
work with. Luckily this is easy to do. If you create a two files, chap1.xml and chap2.xml, and copy and paste the following into
chap1.xml

Hide Copy Code

<chapter><title>On Foo's</title>
<para>
Stuff about Foo's goes here.
</para>
</chapter>

And the following into chap2.xml

Hide Copy Code


<chapter><title>On Bars's</title>
<para>
Stuff about Bars's goes here.
</para>
</chapter>

And modify simple.xml's contents like so:

Hide Copy Code

<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [

<!ENTITY chap1 SYSTEM "chap1.xml">


<!ENTITY chap2 SYSTEM "chap2.xml">
]>

<book>
<title>Simple Book</title>
<titleabbrev>Simple</titleabbrev>

<preface><title>Introduction</title>
<para>
Hello! Here's an introduction!
</para>
</preface>

&chap1;

&chap2;
</book>

The use of the <!ENTITY> tags creates entities named chap1 and chap2. Using them automatically includes their contents in to
the simple.xml file, so be careful to not put the <?xml?> preprocessor tags in the included files (chap1.xml and chap2.xml
respectively). We can verify that all this works by running xsltproc again:

Hide Copy Code

xsltproc --nonet D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl simple.xml

Again we get the same output as before and we have now broken apart our documentation into multiple files for easier editing.

Now lets generate our chm. To do this we simply call the command line HTML help compiler (hhc.exe) and pass the generated hhp
file.

Hide Copy Code

hhc htmlhelp.hhp

And voila! we now have our chm file:


Adding an index

Now that we can create out DocBook output and create our chm file, lets get a little fancier and add support for an index. In
DocBook it's so simple we can do this in a single line, so let's modify simple.xml like so:

Hide Shrink Copy Code

<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [

<!ENTITY chap1 SYSTEM "chap1.xml">


<!ENTITY chap2 SYSTEM "chap2.xml">
]>

<book>
<title>Simple Book</title>
<titleabbrev>Simple</titleabbrev>

<preface><title>Introduction</title>
<para>
Hello! Here's an introduction!
</para>
</preface>
&chap1;

&chap2;

<index id="index"/>
</book>

This now gives indexing support. However to actually ensure an item is placed in the index, we have to indicate which items we
want to mark as being indexed. Doing so is simple, we just use the <indexterm> tag and give the term a name. So let's modify
both chap1.xml and chap2.xml and add some index support:

chap1.xml:

Hide Copy Code

<chapter><title>On Foo's</title>
<para><FONT size=2><indexterm><primary>About Foo's</primary></indexterm></FONT>
Stuff about Foo's goes here.
</para>
</chapter>

chap2.xml:

Hide Copy Code

<chapter><title>On Bars's</title>
<para><FONT size=2><indexterm><primary>About Bar's</primary></indexterm></FONT>
Stuff about Bars's goes here.
</para>
</chapter>

Now just run it through the xsltproc to produce our html output. Then run the compile step again with hhc. Now one thing to note
at this point, there seems to be a bug, because once you add index support, the HTML Help compiler will complain about a
mysteriously missing ix01.html file. It will however properly generate the chm file, complete with indexing support, so I don't know
what the deal is. However it can cause problems with other programs that may run the hhc program from a script as it will now
return an error code, despite successfully creating the chm! We'll address this a bit more later on. And now for our obligatory
screenshot:
Kewl!

Now, lets add one more thing: how to produce a single html file, such as we might want if we were to use DocBook to write an
article for CodeProject. To do this, we'll use the same XML file(s), remember, single documentation source, multiple outputs, but this
time specify a different XSL style sheet to use. We will also not produce any chm file, but only a single html output file. To run the
processor we simply type:

Hide Copy Code

xsltproc --nonet D:/docbook-xsl-1.60.1/html/docbook.xsl simple.xml

Note the change in style sheets, and the fact that it simply dumps the output to stdout. No worries though - we can just dump the
output to a file like so:

Hide Copy Code

xsltproc --nonet D:/docbook-xsl-1.60.1/html/docbook.xsl simple.xml > simple.html

Now we can look out our DocBook documentation, complete with index!
More DocBook tags

All right, up till now we've only seen some pretty basic usage of the various DocBook tags available. While I am not going to
attempt to cover all of them, I will try cover some of the more useful one, at least in my experience. For a more thorough article on
this, please see the online version of "DocBook: The Definitive Guide" from O'Reilly.

Meta data
With DocBook you can describe various peices of information about the documentation, such as the author, legal notices, book
version, and copyright(s) notice. We start this by adding a <bookinfo> tag.

Hide Shrink Copy Code

<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [

<!ENTITY chap1 SYSTEM "chap1.xml">


<!ENTITY chap2 SYSTEM "chap2.xml">
]>

<book>
<bookinfo>
</bookinfo>
<title>Simple Book</title>
<titleabbrev>Simple</titleabbrev>

<preface><title>Introduction</title>
<para>
Hello! Here's an introduction!
</para>
</preface>

&chap1;

&chap2;

<index id="index"/>
</book>

Now we can add a quick legal notice, author, and copyright sections to our simple.xml file:

Hide Copy Code

<book>
<bookinfo>
<legalnotice>
<para>
Here a short legal notice: You agree that all your base
belongs to me!
</para>
</legalnotice>
<author>
<firstname>Bob</firstname>
<surname>Grey</surname>
</author>
<copyright>
<year>2003</year>
<year>2021</year>
<holder>Pennywise the Clown</holder>
</copyright>
</bookinfo>
<title>Simple Book</title>

<!-- ... -->


</book>

Tables

Tables are critical for just about any kind of documentation, and DocBook fully supports them. Lets add a simple one to our
chap1.xml file:

Hide Copy Code

<chapter><title>On Foo's</title>
<para><FONT size=2><indexterm><primary>About Foo's</primary></indexterm></FONT>
Stuff about Foo's goes here.
</para>
<para>And now for some data in a table:
<table frame="none" pgwide="1">
<tgroup cols="3" align="left" colsep="1" rowsep="1">
<thead>
<row>
<entry>Column 1</entry>
<entry>Column 2</entry>
<entry>Column 3</entry>
</row>
</thead>
<tbody>
<row>
<entry>Heres</entry>
<entry>A</entry>
<entry>Row entry!</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</chapter>

Notice the <tgroup> - this is critical to have, otherwise the table will not get rendered correctly. When we process this, we'll see
some thing like this:

Chapter 1. On Foo's
Stuff about Foo's goes here.

And now for some data in a table:

Table 1.1.

Column 1 Column 2 Column 3


Heres A Row entry!
Note that DocBook automatically add table numbering for you and ties it to your chapters numbers. If we had 3 tables in chapter
2, we'd see them numbered as Table 2.1, Table 2.2, and Table 2.3. We'll see how to turn off the table numbering later on.

Links

In DocBook there are several way to link to things. I'll show you how to link to external URL's and to items within your DocBook
documentation.

To link to external URL's you use the <ulink> tag as follows:

chap2.xml:

Hide Copy Code

<chapter><title>On Bars's</title>
<para><FONT size=2><indexterm><primary>About Bar's</primary></indexterm></FONT>
Stuff about Bars's goes here.
</para>
<para>To learn more about the wonderful world of Bar's look
<ulink url="http://www.google.com/search?q=Bars">
here
</ulink>
</para>
</chapter>

The url attribute specifies the link to load.

Graphics

Now we certainly couldn't write documentation without graphics! Adding graphics into your documentation is accomplished with
the <graphic> tag. For example:

chap2.xml:

Hide Copy Code

<chapter><title>On Bars's</title>
<para><FONT size=2><indexterm><primary>About Bar's</primary></indexterm></FONT>
Stuff about Bars's goes here.
</para>
<para>To learn more about the wonderful world of Bar's look
<ulink url="http://www.google.com/search?q=Bars">
here
</ulink>
</para>
<para>
Don't forget: Graphics are important!
<graphic fileref="smiley.bmp"></graphic>
</para>
</chapter>

Note the fileref attribute - this is what points to the file. Fileref can point to a url, for example, fileref="
</FONT>http://images.sourceforge.net/head_bg_new.gif" is also valid syntax.

Notes
Adding notes is another really cool feature of DocBook. A note is a little paragraph that stands out, usual with some kind of extra, or
special case documentation about a feature. For example:

chap2.xml:

Hide Copy Code

<chapter><title>On Bars's</title>
<para><FONT size=2><indexterm><primary>About Bar's</primary></indexterm></FONT>
Stuff about Bars's goes here.
</para>
<para>To learn more about the wonderful world of Bar's look
<ulink url="http://www.google.com/search?q=Bars">
here
</ulink>
</para>
<para>
Don't forget: Graphics are important!
<graphic fileref="smiley.bmp"></graphic>
</para>
<note>
Not only can DocBook do graphics, but it can handle notes as well!
Isn't that just cool?
</note>
</chapter>

DocBook renders this as:

Chapter 2. On Bars's
Stuff about Bars's goes here.

To learn more about the wonderful world of Bar's look here

Don't forget: Graphics are important!

Note

Not only can DocBook do graphics, but it can handle notes as well! Isn't that just cool?
Special Formatting

In general formatting is not something that is relevant to DocBook. The idea is that DocBook is for specifying content and
formatting is handled via CSS style sheets. However there are a few tags you can use. For example, the most common is the
<emphasis> tag, used like so:

chap1.xml file:

Hide Shrink Copy Code

<chapter><title>On Foo's</title>
<para><FONT size=2><indexterm><primary>About Foo's</primary></indexterm></FONT>
Stuff about Foo's goes here.
</para>
<para>And now for some data in a table:
<table frame="none" pgwide="1">
<tgroup cols="3" align="left" colsep="1" rowsep="1">
<thead>
<row>
<entry>Column 1</entry>
<entry>Column 2</entry>
<entry>Column 3</entry>
</row>
</thead>
<tbody>
<row>
<entry>Heres</entry>
<entry>A</entry>
<entry>Row entry!</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
Not only are Foo's important to proper software development, but they are
critical to understanding the synergistic relationship between Neo
<emphasis>and</emphasis> Trinity.
</para>
</chapter>

DocBook renders it like so:

Chapter 1. On Foo's
Stuff about Foo's goes here.

And now for some data in a table:

Table 1.1.

Column 1 Column 2 Column 3


Heres A Row entry!
Not only are Foo's important to proper software development, but they are critical to understanding the synergistic relationship
between Neo and Trinity.

Plain text formatting

Sometimes you'll want to include program listings, or plain unformatted text, say a console dump to demonstrate a command line
program. For source listing, a frequent way to do this is the <programlisting> tag. For example:

chap1.xml file:

Hide Shrink Copy Code

<chapter><title>On Foo's</title>
<para><FONT size=2><indexterm><primary>About Foo's</primary></indexterm></FONT>
Stuff about Foo's goes here.
</para>
<para>And now for some data in a table:
<table frame="none" pgwide="1">
<tgroup cols="3" align="left" colsep="1" rowsep="1">
<thead>
<row>
<entry>Column 1</entry>
<entry>Column 2</entry>
<entry>Column 3</entry>
</row>
</thead>
<tbody>
<row>
<entry>Heres</entry>
<entry>A</entry>
<entry>Row entry!</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
Not only are Foo's important to proper software development, but they are
critical to understanding the synergistic relationship between Neo
<emphasis>and</emphasis> Trinity.
</para>
<para>
Here's an example of a code listing:
<programlisting>
int foo = 12 * 23;

multiply_endlessly( foo );

</programlisting>
</para>
</chapter>

A frequent thing you need in a program listing is the use of the < or > characters. If you simple use them in your content, you'll get
errors when you go to process the DocBook files. However, if you use the CDATA tags you can put any characters you please in the
listing, they'll be ignored till the processor encounters the closing CDATA tag. An example:

chap1.xml file:

Hide Shrink Copy Code

<chapter><title>On Foo's</title>
<para><FONT size=2><indexterm><primary>About Foo's</primary></indexterm></FONT>
Stuff about Foo's goes here.
</para>
<para>And now for some data in a table:
<table frame="none" pgwide="1">
<tgroup cols="3" align="left" colsep="1" rowsep="1">
<thead>
<row>
<entry>Column 1</entry>
<entry>Column 2</entry>
<entry>Column 3</entry>
</row>
</thead>
<tbody>
<row>
<entry>Heres</entry>
<entry>A</entry>
<entry>Row entry!</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
Not only are Foo's important to proper software development, but they are
critical to understanding the synergistic relationship between Neo
<emphasis>and</emphasis> Trinity.
</para>
<para>
Here's an example of a code listing:
<programlisting>
<![CDATA[
int foo = 12 * 23;
std::vector<int> vec;
vec.push_back( foo );

]]>
</programlisting>
</para>
</chapter>

Using the CDATA tag makes it much easier to handle special characters that are common in programming, but are also used in
XML, and it's much nicer to read than a whole bunch of "&lt;" tags.

Faqs

Writing FAQ's is common with technical documentation, particularly if it is documentation that is destined for online usage.
DocBook provides some neat tags that support this as well. To do this, lets create a new xml file, faqs.xml, and add the appropriate
entity to our main xml file, like so:
Hide Shrink Copy Code

<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [

<!ENTITY chap1 SYSTEM "chap1.xml">


<!ENTITY chap2 SYSTEM "chap2.xml">
<!ENTITY faqs SYSTEM "faqs.xml">
]>

<book>
<bookinfo>
<legalnotice>
<para>
Here a short legal notice: You agree that all your base
belongs to me!
</para>
</legalnotice>
<author>
<firstname>Bob</firstname>
<surname>Grey</surname>
</author>
<copyright>
<year>2003</year>
<year>2021</year>
<holder>Pennywise the Clown</holder>
</copyright>
</bookinfo>

<title>Simple Book</title>
<titleabbrev>Simple</titleabbrev>

<preface><title>Introduction</title>
<para>
Hello! Here's an introduction!
</para>
<preface>

&chap1;

&chap2;

&faqs;
<index id="index"/>
</book>

Now edit your faqs.xml like so:

Hide Copy Code

<section><title>FAQs</title>
<qandaset><title></title>
<qandaentry>
</qandaentry>
</qandaset>
</section>

Faqs can be organized in question and answer sets, which provide a way to organize the individual questions and answers into
logical groups. The sets can be broken into entries (<qandaentry> tags), and then each entry can have it's series of question and
answer tags. To fill this out, lets add some arbitrary question and answers, which, hopefully, will impart our deep and profound
wisdom unto the reader:

Hide Shrink Copy Code

<section><title>FAQs</title>
<qandaset><title>The Big Questions</title>
<qandaentry>
<question>
<para>Why did the chicken cross the road?</para>
</question>
<answer>
<para>
To get to the chicken feed.
</para>
</answer>
<question>
<para>Will anyone, in fact, ever need more than 640K of memory?</para>
</question>
<answer>
<para>
Two words: "Doom III".
</para>
</answer>
</qandaentry>
</qandaset>
<qandaset><title>Even Bigger Questions!</title>
<qandaentry>
<question>
<para>Is Neo really the One?</para>
</question>
<answer>
<para>
That all depends on your perception of both reality, and your
understanding of sub-atomic quantum scale micro causality. In
addition, this will require a support call to Technical Support.
Please call 1-888-232-1NEO.
</para>
</answer>
<question>
<para>Is VB really cooler than C++?</para>
</question>
<answer>
<para>
No. Thanks for playing.
</para>
</answer>
</qandaentry>
</qandaset>
</section>

Save this, process it, and we see something like:

FAQs
The Big Questions

1. Why did the chicken cross the road?

1. Will anyone, in fact, ever need more than 640K of memory?

1.
Why did
the
chicken
cross the
road?

To get to
the
chicken
feed.

1.
Will
anyone,
in fact,
ever
need
more
than
640K of
memory?

Two
words:
"Doom
III".

Even Bigger Questions!

1. Is Neo really the One?

1. Is VB really cooler than C++?

1.
Is Neo really
the One?

That all
depends on
your
perception of
both reality,
and your
understanding
of sub-atomic
quantum
scale micro
causality. In
addition, this
will require a
support call to
Technical
Support.
Please call 1-
888-232-
1NEO

1.
Is VB really
cooler than
C++?

No. Thanks
for playing.

Customizing the Style Sheet

So far we have covered the basics of producing our DocBook content, but at some point you're going to want to control what it's
output looks like. As an example of what you can do, I humbly submit my own work with it, the VCF Documentation. This content is
simply regular DocBook, but through heavy customization of the style sheets I have been able to control things like header, footers,
CSS, where standard DocBook images are looked for, and even how internal links are formatted. So to get started lets create our
style sheet, and call it simple.xsl. Then lets add the boiler plate basics:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
</xsl:stylesheet>

Note the <xsl:import> tag, this tells the processor to import, or include, the URL referred to by the href attribute. In our case
we are going to refer to our local htmlhelp.xsl style sheet. This is the same style sheet that we were using earlier in the arguments
that we passed to the xsltproc program, only now we are "inheriting" from it by including it here. From here on out our command
line to xsltproc will look like this:

Hide Copy Code

xsltproc --nonet simple.xsl simple.xml

This will now replace the default HTML Help style sheet with our custom style sheet, which we will now start to add our specific
changes to.
The style sheets use XSL which is, as I understand it, and I am by no means an expert here, a sort of XML like programming syntax
that lets you tell the processor (in our case xsltproc) what to do with the XML tree that is built as a result of a successful parsing of
the XML source file (in our case simple.xml).

Our first customizations will be simple ones, where we'll see how to turn on (or off) various parameters that DocBook uses in it's
style sheets. So the first thing we'll do is to ensure that the legal info we have is generated (and linked to) as a separate output file
(in this case html). To do this we add the following:

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
</xsl:stylesheet>

Note how we did this: by add a new line using the <xsl:param> tag we can specify a certain parameter's value. In this case we
specified that the "generate.legalnotice.link" parameter should have a value of 1, or true.

Next we'll make sure that the "Next" and "Back" navigation links at the bottom of each page is enabled. When generating HTML
Help output, the default style sheet turns this off, meaning that we won't see it. We are going to turn it on here:

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
</xsl:stylesheet>

We select 0, or false, into the "suppress.navigation" variable to ensure that the navigation links are made visible.

The next set will tell the DocBook to make use of the standard DocBook graphics for tags like <note>. DocBook provides a
standard set of images for various tags.  

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admin.graphics" select="1"/>
</xsl:stylesheet>

Once you have turned the default DocBook images on, you also need to specify where they live. By default, the links to them will be
"images/<imagename>.png". So if you do not have an "images" directory and you have no png images, then you'll end up
with the ugly broken image warning in the browser's rendering of the page. So, to fix this, lets tell DocBook what directory our
images will be in:

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admin.graphics.path">gfx/</xsl:param>
</xsl:stylesheet>

Now lets create our images directory:

Hide Copy Code

mkdir gfx

Then just copy over all the png files from your DB's "images" directory (in our case, D:/docbook-xsl-1.60.1/images) into your new gfx
directory.

process your DocBook files through xsltproc and you should see this:

Chapter 2. On Bars's
Stuff about Bars's goes here.

To learn more about the wonderful world of Bar's look here

Don't forget: Graphics are important!

<IMG alt=[Note] Note


src="/KB/winhelp/docbook_howto/note.png"> Not only can DocBook do graphics, but it can handle notes as well!
Isn't that just cool?

Now the note we added has a little hand pointer graphic! This happens whenever you use the <note> tag, with no worrying
about the graphics content. You can create your own image to use as well, so long as it is in the gfx directory and named note.png.
Adding CSS support

OK so we have seen how to control some of the basic variables used in outputting our processed DocBook documentation. Now
lets look at how to control the content look via CSS style sheets. First let's create a simple CSS file called simple.css. Then add the
following to it:

Hide Copy Code

a, body, div, table, td


{
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
}
body
{
background-color: #DDDDDD;
color: #000000;
margin: 0px 0px 0px 0px;
padding : 0px 5px 5px 5px;
border: 1px solid #000000;
}

If you're not familiar with how CSS works, here's a Google link to a variety of potential information about it. Basically we have
declared that any <a>, <body>, <div>, <table>, or <td> tags will use some sort of sans serif font, preferably a font named
Verdana, Geneva, Arial, or Helvetica. Furthermore, we have declared that the <body> tag should use a background color of light
grey, a text color of black, have no margins whatsoever, and have a 1 pixel solid black border.

To actually get DocBook to use this CSS sheet, we need to now customize out simple.xsl file, as follows:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
</xsl:stylesheet>

This instructs DocBook to use the CSS file that we specify in the "select" attribute, in our case the simple.css file. If you run the
processor again, you'll see that we now have html that uses the style sheets specifications!

More Style Sheet customizations

There are a lot of things you can do when customizing the style sheets, so we'll look at a few more simple parameters that we can
change, as well as some advanced changes, like adding a header and footer.

Lets adjust the file name for the chm file that will be produced when we run the hhc HTML Help compiler. Lets once again change
simple.xsl to the following:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
<xsl:param name="htmlhelp.chm" select="'simple.chm'"/>
</xsl:stylesheet>

Adding this line now lets us control the name of the chm file that is produced!

Next we'll specify whether or not we should create a binary TOC or not, and whether the TOC icons should be folders or the more
traditional book icon.

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
<xsl:param name="htmlhelp.chm" select="'simple.chm'"/>
<xsl:param name="htmlhelp.hhc.binary" select="0"/>
<xsl:param name="htmlhelp.hhc.folders.instead.books" select="0"/>
</xsl:stylesheet>

Next, we'll control how deep various sections should be shown. Each time you nest a <section> tag inside another <section>
tag it causes a new level of numbering (i.e. 1.1, and it's first child 1.1.1). The top of each page can display a certain amount of the
pages sections and sub sections in a TOC style set of links. By adjusting the style sheet, we can control how deep this goes.

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
<xsl:param name="htmlhelp.chm" select="'simple.chm'"/>
<xsl:param name="htmlhelp.hhc.binary" select="0"/>
<xsl:param name="htmlhelp.hhc.folders.instead.books" select="0"/>
<xsl:param name="toc.section.depth" select="4"/>
</xsl:stylesheet>

Next lets move on to adding a custom html header to the top of all the pages. To do this we'll override the default behavior for the
XSL processing of a certain template. So the first thing we'll add is the initial tags for overriding the template, like so:
simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
<xsl:param name="htmlhelp.chm" select="'simple.chm'"/>
<xsl:param name="htmlhelp.hhc.binary" select="0"/>
<xsl:param name="htmlhelp.hhc.folders.instead.books" select="0"/>
<xsl:param name="toc.section.depth" select="4"/>
<xsl:template name="user.header.navigation">
</xsl:template>
</xsl:stylesheet>

Now within the <xsl:template> tag we can put whatever HTML we want, and it will automatically be added to the beginning of
each page, after the <body> tag, and before any of our DocBook content! So lets try this:

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
<xsl:param name="htmlhelp.chm" select="'simple.chm'"/>
<xsl:param name="htmlhelp.hhc.binary" select="0"/>
<xsl:param name="htmlhelp.hhc.folders.instead.books" select="0"/>
<xsl:param name="toc.section.depth" select="4"/>
<xsl:template name="user.header.navigation">
<hr>
<p>Documentation by ACME Data Inc. No Coyote's allowed.</p>
<hr>
</xsl:template>
</xsl:stylesheet>

Our custom header simply consists of two horizontal rules and some silly text in between them. However if we process this we get
some strange errors:

Hide Copy Code

$ xsltproc --nonet simple.xsl simple.xml


simple.xsl:22: error: Opening and ending tag mismatch: hr and xsl:template
</xsl:template>
^
simple.xsl:23: error: Opening and ending tag mismatch: hr and xsl:stylesheet
</xsl:stylesheet>
^
simple.xsl:23: error: Premature end of data in tag xsl:template
</xsl:stylesheet>
^
simple.xsl:23: error: Premature end of data in tag xsl:stylesheet
</xsl:stylesheet>
^
cannot parse simple.xsl

Unfortunately the xsltproc is expecting XML compliant tags, while standard HTML does not enforce this. So while <hr> is perfectly
acceptable HTML syntax it is not acceptable to XML parsers. Luckily we can write <hr></hr> and still be acceptable to browsers.
So a quick change:

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
<xsl:param name="htmlhelp.chm" select="'simple.chm'"/>
<xsl:param name="htmlhelp.hhc.binary" select="0"/>
<xsl:param name="htmlhelp.hhc.folders.instead.books" select="0"/>
<xsl:param name="toc.section.depth" select="4"/>
<xsl:template name="user.header.navigation">
<hr></hr>
<p>Documentation by ACME Data Inc. No Coyote's allowed.</p>
<hr></hr>
</xsl:template>
</xsl:stylesheet>

Once processed we something like the following (minus the changes the CSS would have made):

Documentation by ACME Data Inc. No Coyote's allowed.

Simple Book
Next

Simple Book
Bob Grey

Copyright © 2003, 2021 Pennywise the Clown

Legal Notice

Table of Contents
Introduction

1. On Foo's

2. On Bars's

List of Tables

1.1.

Next
Introduction

Note our custom header at the top - this would appear on each page we navigate to!

Adding a custom footer is quite similar, first we add our <xsl:template> overrides:

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
<xsl:param name="htmlhelp.chm" select="'simple.chm'"/>
<xsl:param name="htmlhelp.hhc.binary" select="0"/>
<xsl:param name="htmlhelp.hhc.folders.instead.books" select="0"/>
<xsl:param name="toc.section.depth" select="4"/>
<xsl:template name="user.header.navigation">
<hr></hr>
<p>Documentation by ACME Data Inc. No Coyote's allowed.</p>
<hr></hr>
</xsl:template>
<xsl:template name="user.footer.navigation">
</xsl:template>
</xsl:stylesheet>

Note we are customizing the "user.footer.navigation" template, as opposed to the previous customization of the
"user.header.navigation" template. Finally lets add our html footer:

simple.xsl:

Hide Copy Code

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">
<xsl:import href="D:/docbook-xsl-1.60.1/htmlhelp/htmlhelp.xsl"/>
<xsl:param name="generate.legalnotice.link" select="1"/>
<xsl:param name="suppress.navigation" select="0"/>
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">gfx/</xsl:param>
<xsl:param name="html.stylesheet" select="'simple.css'"/>
<xsl:param name="htmlhelp.chm" select="'simple.chm'"/>
<xsl:param name="htmlhelp.hhc.binary" select="0"/>
<xsl:param name="htmlhelp.hhc.folders.instead.books" select="0"/>
<xsl:param name="toc.section.depth" select="4"/>
<xsl:template name="user.header.navigation">
<hr></hr>
<p>Documentation by ACME Data Inc. No Coyote's allowed.</p>
<hr></hr>
</xsl:template>

<xsl:template name="user.footer.navigation">
<hr></hr>
<p>The Road Runner was here - All Wrongs Reserved.</p>
<hr></hr>
</xsl:template>
</xsl:stylesheet>

And once again, if we process this, like before, we'll now see this footer applied to each page of our documentation!

Adding automatic version numbering: fun with sed

At this point we've covered most of the basics of actually using DocBook and processing our content. However, what we frequently
want to do with our documentation is to have some section of it labeled with a version, one that matches up with the software it is
documenting. As far as I know DocBook offers no real support for this, so we'll look at doing it the "hard" way. The process I'll
describe is a pretty typical one for OSS projects. I don't know how frequently it is used in the Win32 world, but it does work, and is
pretty flexible. What we'll end up with is a special file that keeps our version number. Then we'll write a simple script that reads the
file into a variable, and then performs a find-and-replace in our simple.xml where we'll have referenced the version number using a
variable name, which will then be replaced. To accomplish this we'll use sed, a unix program that can, among many other things,
perform this find and replace operation for us.

First lets create a file appropriately called, version.txt. Add the following line to it:

Hide Copy Code

1.2.3

Verify it's contents by using the cat command:

Hide Copy Code

$ cat version.txt
1.2.3

Now alter the simple.xml to use a version variable to describe it's documentation version.

Hide Shrink Copy Code

<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [

<!ENTITY chap1 SYSTEM "chap1.xml">


<!ENTITY chap2 SYSTEM "chap2.xml">
<!ENTITY faqs SYSTEM "faqs.xml">
]>
<book>
<bookinfo>
<legalnotice>
<para>
Here a short legal notice: You agree that all your base
belongs to me!
</para>
</legalnotice>
<author>
<firstname>Bob</firstname>
<surname>Grey</surname>
</author>
<copyright>
<year>2003</year>
<year>2021</year>
<holder>Pennywise the Clown</holder>
</copyright>
</bookinfo>

<title>Simple Book Version BOOK_VERSION</title>


<titleabbrev>Simple</titleabbrev>

<preface><title>Introduction</title>
<para>
Hello! Here's an introduction!
</para>
</preface>

&chap1;

&chap2;

&faqs;
<index id="index"/>
</book>

Note where we added the "Version BOOK_VERSION" the text "BOOK_VERSION" will be used as a place holder for the actual version
stored in the version.txt file.

Next lets assign a variable in the shell to the contents of the version.txt file:

Hide Copy Code

$ bk_ver=`cat version.txt`

Notice the use of the ` `, or back quotes. This tells the shell to assign to the variable bk_ver whatever the output is that came from
executing the text in the back quotes. To test this:

Hide Copy Code

$ echo $bk_ver
1.2.3

So far so good. Now lets get really icky and introduce our little sed script:

Hide Copy Code

sed "s?BOOK_VERSION?$bk_ver?g" simple.xml > simple.xml.tmp


This will find the string "BOOK_VERSION" in the file simple.xml and replace it with the contents of the variable bk_ver, and then
dump the output of all this to the file simple.xml.tmp. The original file, simple.xml, will be left alone for now.

Run this, and simple.xml.tmp now contains:  

Hide Shrink Copy Code

<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [

<!ENTITY chap1 SYSTEM "chap1.xml">


<!ENTITY chap2 SYSTEM "chap2.xml">
<!ENTITY faqs SYSTEM "faqs.xml">
]>

<book>
<bookinfo>
<legalnotice>
<para>
Here a short legal notice: You agree that all your base
belongs to me!
</para>
</legalnotice>
<author>
<firstname>Bob</firstname>
<surname>Grey</surname>
</author>
<copyright>
<year>2003</year>
<year>2021</year>
<holder>Pennywise the Clown</holder>
</copyright>
</bookinfo>

<title>Simple Book Version 1.2.3</title>


<titleabbrev>Simple</titleabbrev>

<preface><title>Introduction</title>
<para>
Hello! Here's an introduction!
</para>
</preface>

&chap1;

&chap2;

&faqs;
<index id="index"/>
</book>

Notice our version number!

Now we can just copy a temporary version of simple.xml (say to simple.xml.orig), rename simple.xml.tmp to simple.xml, and run the
processor over it, and viola! we get a nice version number in our documentation. Then if we now rename our older copy of
simple.xml.orig to simple.xml, we have the old file back and ready to edit.
Automating the process: Make to the rescue!

Now while the above does work, it is kind of a pain to remember, so let's get even more sophisticated and create a small makefile
to do all this for us. Makefile's, for those of you blessed enough to not have encountered this rather cryptic syntax, are a script that
you write that defines a series of targets and dependencies, and rules for building each one. You create a Makefile, and then run it
through a program called "make". I'll be using the syntax of the more traditional Unix make (specifically that compatible with GNU
make program), not the goofier variants espoused by Microsoft or Borland. We could jsut write a script, but using a makefile
automates certain parts for us, especially if we want to add other features later on.

Makefiles list each target, followed by a ":", and then a series of 0 or more dependencies, separated by whitespace. The "#" is a
single line comment. After a target, you can have a series of one or more rules. Each rule must be preceded by a single TAB
character. I repeat, you must precede the rule by a TAB or make will crap out on you. Of course this is a stupid requirement, but
that's make for you. Each target can be a file or just a symbolic name. If the target is a file name, make will attempt to determine if it
is "up to date" (based on it's dependencies) before going ahead and building the target. If the target is a symbolic name (like
ArdVark) it will always get built. So, without further ado, lets create our Makefile like so (make sure the file is just named Makefile):

Hide Copy Code

#Here's out simple makefile


#for the simple documentation

book_ver = `cat version.txt`

docs:
sed "s?BOOK_VERSION?$(book_ver)?g" simple.xml > simple.xml.tmp
cp simple.xml simple.xml.orig
mv simple.xml.tmp simple.xml
xsltproc --nonet simple.xsl simple.xml
-hhc htmlhelp.hhp
mv simple.xml.orig simple.xml

Our Makefile has one variable book_ver. We can access it's value by using the $(<variable name>) syntax. We have one target
"docs" with no dependcies, so it will always be built. If any rule fails (the execution returns a non-zero value) make will stop. If you
remember our earlier issue with the HTML Help compiler and it not returning a succesful return code, despite actually creating the
correct chm file, you'll see that we use a "-" character before the hhc rule. Using the "-" character tells make to ignore the return
code and proceed on, even if the rule "fails".

Save the Makefile and then run make:

Hide Copy Code

make docs

You should see the commands run and at the end of it all, you should end up with a simple.chm with the correct version, as
specified in version.txt, and the original simpl.xml should still have it's "BOOK_VERSION" placeholder in it.

We're going to add one final thing to wrap this all up. Wouldn't it be neat if we could make a single file that we could use to hold all
the current source documents that we are currently working on? It sure would! So lets add one more target to our make file:

Makefile:

Hide Shrink Copy Code

#Here's out simple makefile


#for the simple documentation
book_ver = `cat version.txt`

docs_files = simple.xml \
simple.xsl \
simple.css \
chap1.xml \
chap2.xml \
faqs.xml \
Makefile \
gfx/note.png \
smiley.bmp \
version.txt

docs:
sed "s?BOOK_VERSION?$(book_ver)?g" simple.xml > simple.xml.tmp
cp simple.xml simple.xml.orig
mv simple.xml.tmp simple.xml
xsltproc --nonet simple.xsl simple.xml
-hhc htmlhelp.hhp
mv simple.xml.orig simple.xml

dist:
mkdir simple-$(book_ver)
cp --parents $(docs_files) simple-$(book_ver)/
tar -cf simple-$(book_ver).tar simple-$(book_ver)/
gzip simple-$(book_ver).tar
rm -rf simple-$(book_ver)/

Save this and if you now run:

Hide Copy Code

make dist

You'll end up with the file simple-1.2.3.tar.gz which has all the source to your documentation! Cool.

There's lots more you can do with make, but I'll leave that as an exercise to the reader to play with that. Hopefully this gives you a
basic starting point.

Conclusion

Well we have covered a whole lot of ground, and hopefully I didn't lose anyone! We've gone over the basics of DocBook content
creation, discussed how to install and process the content to produce html and HTML Help based output. We've customized some
of the style sheets for our own use, and written a makefile to support versioning and producing our DocBook generated HTML
Help. If you have further questions explore the DocBook links I have provided in the article, feel free to email me, or better yet post
a question below. Also, feel free to browse through the VCF's documentation and documentation Makefile. It covers everything in
this article plus offers some other, more advanced, customizations.

License
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in
doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Share
TWITTER FACEBOOK

About the Author


Jim Crafton
Software Developer (Senior) Follow
United States this Member

Currently working on the Visual Component Framework, a really cool C++ framework.
Currently the VCF has millions upon millions upon billions of Users. If I make anymore money
from it I'll have to buy my own country.

You may also be interested in...


Pro Using PDFs to Manage and Share TridentOpt: A Multi-Objective
Content Optimization Engine or Solver

XsdTidy beautifies the Xsd.exe output Introducing SimpleSamSettings


*with full DocBook .NET Wrapper*

Win32 Window Minimal Screen Keyboard

Comments and Discussions

Add a Comment or Question Email Alerts Search Comments


Spacing Relaxed
Relaxed   Layout Normal
Normal   Per page 25
25     Update

First Prev Next

Question about wrappers. alight9010 11-Dec-08 19:59

Re: Question about wrappers. Jim Crafton 11-Dec-08 20:05

doxygen to docbook? sskacar 30-Oct-06 14:47

Code Fix: admon.graphics.path shadowbq 26-Oct-06 1:37

Running xml file through XSL processor does not work psleczkowski 10-Aug-06 22:57

Re: Running xml file through XSL processor does not work masifsharif 22-Jul-09 18:29

Problem with htmlhelp Georgiev 7-Jun-06 7:26

Re: Problem with htmlhelp Jim Crafton 7-Jun-06 7:31

Problem with Makefile for docbook Strandman 23-Dec-05 10:03

Re: Problem with Makefile for docbook David Costanzo 19-Jan-06 11:03

Context Help in DocBook? vserd 11-Oct-05 14:46

Re: Context Help in DocBook? Jim Crafton 11-Oct-05 17:43

Free and easy DocBook on Windows VanEssaKel 8-Jul-05 20:26

how to add an CHM help file into a project (an application) ?? In many nhon_hoa 12-May-05 15:43
IDE!!!

Support for Visual C++ 6.0 ? Johnnyfartpants 4-Nov-04 14:06

Re: Support for Visual C++ 6.0 ? Jim Crafton 9-Nov-04 19:44

pass through html Phil Cruz 3-Nov-04 1:15

Re: pass through html Jim Crafton 9-Nov-04 19:46

ix01.html IainM 7-Jun-04 14:56

DocBook stylesheets are part of cygwin Daniel Dittmar 7-Apr-04 16:54

File inclusion Marcello 4-Apr-04 1:28

Re: File inclusion [modified] [email protected] 9-Jun-06 3:23

docbook and .Net Jonathan de Halleux 20-Feb-04 12:58


Re: docbook and .Net Altsoft Xml2PDF 27-Apr-05 18:22

XInclude vs ENTITY 30-Oct-03 1:03

Last Visit: 17-Oct-18 21:42 Last Update: 18-Oct-18 11:22 Refresh 1 2 3 Next »

General    News    Suggestion    Question    Bug    Answer    Joke    Praise    Rant    Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile Article Copyright 2003 by Jim Crafton
Select Language ​ ▼
Web06-2016 | 2.8.180920.1 | Last Updated 4 Oct 2003 Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid
13,732,655 members 1 901 Member 8848464

Search for articles, questions, tips

home articles quick answers discussions features community help

Articles » Desktop Development » Tree Controls » TreeView Controls


Follow

Dragging tree nodes in C#


Michea77, 24 Jan 2005

  4.80 (68 votes) Rate:

This article shows how to implement an Explorer like treeview drag and drop in C#.

Is your email address OK? You are signed up for our newsletters but your email address is either unconfirmed, or
has not been reconfirmed in a long time. Please click here to have a confirmation email sent so we can confirm
your email address and start sending you newsletters again. Alternatively, you can update your subscriptions.

Download source - 9.15 Kb

Like every other website we use cookies. By using our site you acknowledge that you have read and understand our Cookie Policy,
Privacy Policy, and our Terms of Service. Learn more

Got it!

Allow cookies
Introduction
During the implementation of a C# application, I was faced with the problem of adding drag and drop functionality to a tree view.
So far no problems, but in order to make the whole a bit fancier, I decided to add image dragging too, as it is done by the
Windows Explorer when dragging files or directories. Here I got into troubles, since image dragging isn't supported by the .NET
controls. Not finding satisfactory code in the Internet (maybe I'm not a good surfer...), I decided to try it by myself. Having fun on it,
I improved the code by adding scrolling to the component so that a dragged element can be dropped everywhere on the control.

This article will only briefly describe the basics of drag and drop, as it is quite straightforward to implement and there already are a
lot of good articles about it. The aim of the article is to describe how image dragging and automatic scrolling while dragging can be
implemented in C#.

TreeView Drag and Drop


In order to allow Drag and Drop on a TreeView, the AllowDrop flag must be set and handlers for the the following events (or
some of them) must be implemented:

ItemDrag - This event is fired as soon as a drag operation is started. This event is specific for listviews and treeviews. The
dragged element is passed as an argument of the event. The handler of this event should contain the DoDragDrop() call
that begins the drag and drop operation.
DragOver - This event is fired when the user drags over a drag and drop control with the mouse.
DragEnter - This event is fired when the user moves the mouse onto the control while dragging an element.
DragLeave - This event is fired when the user leaves the control with the mouse while dragging an element.
DragDrop - This event is fired when the user releases the mouse over the drop target.
GiveFeedback - This event gives feedback about the current drag effect and cursor.

Image dragging
The implementation of image dragging requires functionalities that first of all create a ghost image of the dragging element and
then move this image as mouse cursor moves over the TreeView control. Part of the needed functionalities are available in the
ImageList implementation of Win32 (WinAPI). In order to call these functions, I wrote the class DragHelper that accesses them
via P/Invoke.

Hide Shrink Copy Code

public class DragHelper


{
[DllImport("comctl32.dll")]
public static extern bool InitCommonControls();

[DllImport("comctl32.dll", CharSet=CharSet.Auto)]
public static extern bool ImageList_BeginDrag(
IntPtr himlTrack, // Handler of the image list containing the image to drag
int iTrack, // Index of the image to drag
int dxHotspot, // x-delta between mouse position and drag image
int dyHotspot // y-delta between mouse position and drag image
);

[DllImport("comctl32.dll", CharSet=CharSet.Auto)]
public static extern bool ImageList_DragMove(
int x, // X-coordinate (relative to the form,
// not the treeview) at which to display the drag image.
int y, // Y-coordinate (relative to the form,
// not the treeview) at which to display the drag image.
);

[DllImport("comctl32.dll", CharSet=CharSet.Auto)]
public static extern void ImageList_EndDrag();

[DllImport("comctl32.dll", CharSet=CharSet.Auto)]
public static extern bool ImageList_DragEnter(
IntPtr hwndLock, // Handle to the control that owns the drag image.
int x, // X-coordinate (relative to the treeview)
// at which to display the drag image.
int y // Y-coordinate (relative to the treeview)
// at which to display the drag image.
);

[DllImport("comctl32.dll", CharSet=CharSet.Auto)]
public static extern bool ImageList_DragLeave(
IntPtr hwndLock // Handle to the control that owns the drag image.
);

[DllImport("comctl32.dll", CharSet=CharSet.Auto)]
public static extern bool ImageList_DragShowNolock(
bool fShow // False to hide, true to show the image
);

static DragHelper()
{
InitCommonControls();
}
}

The first thing to do when we start dragging an element is to create the ghost image of the tree node. Help is provided by the
function ImageList_BeginDrag which creates for us a ghost image. This function needs as parameter the handler of an
ImageList with the image to be made transparent in it. To create the image of the tree node to drag, a new bitmap is created
and the icon and the label are drawn in it. At the end of the dragging operation, the ghost image is destroyed by a call to the
ImageList_EndDrag function. We do all this in the ItemDrag event handler.

Hide Shrink Copy Code

private void treeView_ItemDrag(object sender,


System.Windows.Forms.ItemDragEventArgs e)
{
// Get drag node and select it
this.dragNode = (TreeNode)e.Item;
this.treeView1.SelectedNode = this.dragNode;

// Reset image list used for drag image


this.imageListDrag.Images.Clear();
this.imageListDrag.ImageSize =
new Size(this.dragNode.Bounds.Size.Width
+ this.treeView1.Indent, this.dragNode.Bounds.Height);

// Create new bitmap


// This bitmap will contain the tree node image to be dragged
Bitmap bmp = new Bitmap(this.dragNode.Bounds.Width
+ this.treeView1.Indent, this.dragNode.Bounds.Height);
// Get graphics from bitmap
Graphics gfx = Graphics.FromImage(bmp);

// Draw node icon into the bitmap


gfx.DrawImage(this.imageListTreeView.Images[0], 0, 0);

// Draw node label into bitmap


gfx.DrawString(this.dragNode.Text,
this.treeView1.Font,
new SolidBrush(this.treeView1.ForeColor),
(float)this.treeView1.Indent, 1.0f);

// Add bitmap to imagelist


this.imageListDrag.Images.Add(bmp);

// Get mouse position in client coordinates


Point p = this.treeView1.PointToClient(Control.MousePosition);

// Compute delta between mouse position and node bounds


int dx = p.X + this.treeView1.Indent - this.dragNode.Bounds.Left;
int dy = p.Y - this.dragNode.Bounds.Top;

// Begin dragging image


if (DragHelper.ImageList_BeginDrag(this.imageListDrag.Handle, 0, dx, dy))
{
// Begin dragging
this.treeView1.DoDragDrop(bmp, DragDropEffects.Move);
// End dragging image
DragHelper.ImageList_EndDrag();
}

When the mouse is now moved while a tree node is dragged, the ghost image should follow the mouse cursor. This is done by the
function ImageList_DragMove. We implement it in the DragOver event handler.

Hide Copy Code

private void treeView1_DragOver(object sender,


System.Windows.Forms.DragEventArgs e)
{
// Compute drag position and move image
Point formP = this.PointToClient(new Point(e.X, e.Y));
DragHelper.ImageList_DragMove(formP.X - this.treeView1.Left,
formP.Y - this.treeView1.Top);

...
}

If we leave the TreeView, the ghost image should disappear, and as soon as we re-enter the control, the image should appear
again. This is done by the functions ImageList_DragLeave and ImageList_DragEnter. The function
ImageList_DragEnter also locks the window for updates to allow a clean dragging of the image. ImageList_DragLeave
respectively releases the update lock. We implement these two functions in the corresponding event handlers
(treeView1_DragEnter and treeView1_DragLeave).

While an element is dragged, Windows automatically changes the mouse cursor according to the drag effect (copy, move, none, ...).
In our example, we use the DragDropEffects.Move drag effect. The mouse cursor we want to have while dragging the ghost
image is the normal pointer cursor. The cursor can be set in the GiveFeedback event handler.
Hide Copy Code

private void treeView1_GiveFeedback(object sender,


System.Windows.Forms.GiveFeedbackEventArgs e)
{
if(e.Effect == DragDropEffects.Move)
{
// Show pointer cursor while dragging
e.UseDefaultCursors = false;
this.treeView1.Cursor = Cursors.Default;
}
else e.UseDefaultCursors = true;

As soon as the user drops the element and thus terminates the dragging operation, the control updates must be unlocked calling
the function ImageList_DragLeave. The DoDragDrop() call (see treeView1_ItemDrag) terminates and the ghost image is
released with ImageList_EndDrag.

Hide Copy Code

private void treeView1_DragDrop(object sender,


System.Windows.Forms.DragEventArgs e)
{
// Unlock updates
DragHelper.ImageList_DragLeave(this.treeView1.Handle);

...

}
}

Scrolling while dragging


Without scrolling, we can not reach each node within a tree while we are dragging an element, unless the tree is entirely visible on
the screen. We begin scrolling the control if the mouse cursor reaches the top or the bottom of the TreeView control. The
scrolling is achieved through the EnsureVisible() method of the TreeNode class. To scroll up, we get the previous visible
node through the property PrevVisibleNode of the TreeNode class, and set it visible. Analogously, we scroll down with the
property NextVisibleNode and a call to EnsureVisible(). As soon as we begin dragging a node, a timer is started. At each
tick of the timer, the current position of the cursor is checked, and if it is near the upper or lower border of the control, the tree is
scrolled. To avoid that the dragging image interferes with the scrolling producing ugly graphical effects, we briefly hide the drag
image and unlock the paint updates with the function ImageList_DragShowNolock. That's it!

Hide Shrink Copy Code

private void timer_Tick(object sender, EventArgs e)


{
// get node at mouse position
Point pt = PointToClient(Control.MousePosition);
TreeNode node = this.treeView1.GetNodeAt(pt);

if(node == null) return;

// if mouse is near to the top, scroll up


if(pt.Y < 30)
{
// set actual node to the upper one
if (node.PrevVisibleNode!= null)
{
node = node.PrevVisibleNode;

// hide drag image


DragHelper.ImageList_DragShowNolock(false);
// scroll and refresh
node.EnsureVisible();
this.treeView1.Refresh();
// show drag image
DragHelper.ImageList_DragShowNolock(true);

}
}
// if mouse is near to the bottom, scroll down
else if(pt.Y > this.treeView1.Size.Height - 30)
{
if (node.NextVisibleNode!= null)
{
node = node.NextVisibleNode;

DragHelper.ImageList_DragShowNolock(false);
node.EnsureVisible();
this.treeView1.Refresh();
DragHelper.ImageList_DragShowNolock(true);
}
}
}

License
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in
doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share
TWITTER FACEBOOK

About the Author


Michea77
Web Developer Follow
Switzerland this Member

No Biography provided
You may also be interested in...
XHtmlTree - Tree control with support Computer Temperatures, Fan Speeds,
for HTML, XML, Smart Checkboxes, and etc.
Drag & Drop

Tree Editor Tree-Painter

Learn 3D Math made by the GPU by Graphical BinaryTrees


Creating a 3D Engine on CPU

Comments and Discussions

Add a Comment or Question Email Alerts Search Comments

Spacing Relaxed
Relaxed   Layout Normal
Normal   Per page 25
25     Update

First Prev Next

good job atisah 28-Dec-17 23:27

this.treeView1.PointToClient, not this.PointToClient NikolaB 4-Apr-16 22:46

Can I please use this for a project 20-Oct-14 11:40

nyc post Parul45 1-Jun-12 8:32


My vote of 5 EricBK 12-Apr-12 16:48

Nice article TadTK 8-Apr-12 18:49

Change the position of the gost image nethsu 10-Jan-11 10:13

ImageList can be used! orientalCSharp 22-Jun-10 8:56

Seperator Bar lewisv 20-May-10 0:29

Problem if error comes between BeginDrag and EndDrag... unknown1610 30-Apr-10 14:52

how to show the ghost image when we leave the treeview? cpw999cn 12-Oct-09 10:43

Re: how to show the ghost image when we leave the treeview? Quazistax 26-Mar-10 22:14

Tree restrictions dede_dafreak 23-Jun-09 13:09

Reording nodes JimLaVine 7-Jun-09 5:43

Re: Reording nodes thebeard 3-Jul-09 4:08

Great Work Richard Blythe 18-May-09 18:52

Cannot open project (VS05) FransClasener 8-Jun-08 23:14

Great artical w/update to a small issue when using Greg Cadmes 6-Mar-08 2:44
TreeViewDrawMode.OwnerDrawText

Very good article. Thank you. David Catriel 20-Feb-08 21:03

How can this be extended to enable Drag amnd Drop of multiple vinutha kempanna 20-Feb-08 20:04
nodes. [modified]

Problem in MdiChild form Dejan Stojanovic 1-Nov-07 11:19

SelectedNode trail problem with this code RageKing 30-Oct-07 1:36

Re: SelectedNode trail problem with this code darkzangel 14-May-08 15:38

Nodes MouseHover Event . unitecsoft 8-Aug-07 10:46

how to highlights XtraTreelist nodes dragging from Grid Shantanu Behera 18-Apr-07 10:27

Last Visit: 1-Jan-00 7:00 Last Update: 16-Oct-18 21:29 Refresh 1 2 3 Next »

General    News    Suggestion    Question    Bug    Answer    Joke    Praise    Rant    Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile Article Copyright 2005 by Michea77
Select Language ​ ▼
Web04-2016 | 2.8.180920.1 | Last Updated 24 Jan 2005 Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid
United States (English) Sign in

Home Library Learn Downloads Troubleshooting Community Forums

Ask a question Search related threads Search forum questions Submit

Quick access

Answered by: GetElementFromPoint in WebBrowser - e.ClientMousePosition

.NET Framework > Windows Presentation Foundation (WPF)

Question

Hi,

Is it possible to have a DocumentOnClick event for my WebBrowser in WPF?

What I want to do is convert this code from WinForms to WPF;


0
Sign in
private void Document_Click(object sender, HtmlElementEventArgs e)
to vote
{
HtmlElement button = webBrowser1.Document.GetElementFromPoint(e.ClientMousePosition);
textBox1.Text = button.InnerText;

}
So, what I want to achieve is when I click on a text that is in my browser, it should go to the textBox.
What I do with this is to make if statements with different events depending on which Element you click.
But I got that figured out, the only issue is to determine which Element was pressed.

-Vincent

Sunday, August 17, 2014 12:15 PM

Reply | Quote

Answers

This link has a fair bit of stuff in it.

http://www.codegain.com/articles/wpf/ieprogramming/working-with-webbrowser-in-wpf.aspx

.
0
Sign in The straight forward way is to inject functions into the page header.
to vote
You can attach javascript to the document header as you load it.

That can wait until the dom has loaded. walk the dom and attach a function to every type of control you want to
identify clicks on.

Passing back the control id or whatever.

Attaching a script:

http://stackoverflow.com/questions/153748/how-to-inject-javascript-in-webbrowser-control

HtmlDocument doc = browser.Document;


HtmlElement head = doc.GetElementsByTagName("head")[0];
HtmlElement s = doc.CreateElement("script");
s.SetAttribute("text","function sayhello() { alert('hello'); }");
head.AppendChild(s);
browser.Document.InvokeScript("sayHello");

Walking the dom.

http://www.javascriptcookbook.com/article/Traversing-DOM-subtrees-with-a-recursive-walk-the-DOM-function

You'd use that to identify whatever you are interested in attaching a click to.

http://stackoverflow.com/questions/9800310/add-event-handler-to-html-element-using-javascript

pass the element to the click

http://stackoverflow.com/questions/13893138/javascript-click-event-listener-on-multiple-elements-and-get-
target-id

articles = document.getElementsByTagName('article');
articles.addEventListener('click',redirect,false);
function redirect(e){
alert(e.target.id);
}

And that first link tells you about firing c# methods from javascript.

Hope that helps


Please don't forget to up vote answers you like or which help you and mark one(s) which answer your question.

Edited by Andy ONeill Moderator Tuesday, August 19, 2014 2:20 PM


Marked as answer by Vincent Gio Tuesday, August 19, 2014 6:24 PM

Tuesday, August 19, 2014 2:20 PM Moderator

Reply | Quote

All replies

Hi Vincent,

With Silverlight I am used to using the html bridge and communicating to and from the Silverlight application
using javascript.
1 I would tend to attach a script to the page so it told wpf what's happening rather than the other way round.
Sign in
to vote
I'm reasonably confident in javascript though.

This article here describes an approach:

http://www.codegain.com/articles/wpf/ieprogramming/working-with-webbrowser-in-wpf.aspx

But

You if you're not so comfortable with javascript it might make more sense to go with the solution here:

http://stackoverflow.com/questions/9110388/web-browser-control-how-to-capture-document-events

and

public partial class MainWindow : Window


{
public MainWindow()
{
InitializeComponent();
webBrowser1.LoadCompleted += new LoadCompletedEventHandler(webBrowser1_LoadCompleted);
}

private void webBrowser1_LoadCompleted(object sender, NavigationEventArgs e)


{
mshtml.HTMLDocument doc;
doc = (mshtml.HTMLDocument)webBrowser1.Document;
mshtml.HTMLDocumentEvents2_Event iEvent;
iEvent = (mshtml.HTMLDocumentEvents2_Event)doc;
iEvent.onclick += new mshtml.HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);
}

private bool ClickEventHandler(mshtml.IHTMLEventObj e)


{
textBox1.Text = "Item Clicked";
return true;
}
}

Hope that helps


Please don't forget to up vote answers you like or which help you and mark one(s) which answer your question.

Sunday, August 17, 2014 6:24 PM Moderator

Reply | Quote

Hello Andy,

I tried this and done some edits on it, any way that would seem legit for WPF.

0 mshtml.HTMLDocument doc;
Sign in
to vote
private void browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
mshtml.HTMLDocument doc;
doc = (mshtml.HTMLDocument)browser.Document;
mshtml.HTMLDocumentEvents2_Event iEvent;
iEvent = (mshtml.HTMLDocumentEvents2_Event)doc;
iEvent.onclick += new mshtml.HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);
}
private bool ClickEventHandler(mshtml.IHTMLEventObj e)
{
IHTMLElement button = doc.GetElementFromPoint(e.ClientMousePosition);
return true;
}
Getting these errors;

'mshtml.IHTMLEventObj' does not contain a definition for 'ClientMousePosition' and no extension method
'ClientMousePosition' accepting a first argument of type 'mshtml.IHTMLEventObj' could be found (are you
missing a using directive or an assembly reference?)

'mshtml.HTMLDocument' does not contain a definition for 'GetElementFromPoint' and no extension method
'GetElementFromPoint' accepting a first argument of type 'mshtml.HTMLDocument' could be found (are you
missing a using directive or an assembly reference?)

There must be a way, right?


Regards,

Vincent

Sunday, August 17, 2014 6:45 PM

Reply | Quote

Hello Andy,

I tried this and done some edits on it, any way that would seem legit for WPF.

0 mshtml.HTMLDocument doc;
Sign in
to vote

private void browser_LoadCompleted(object sender,


System.Windows.Navigation.NavigationEventArgs e)
{
mshtml.HTMLDocument doc;
doc = (mshtml.HTMLDocument)browser.Document;
mshtml.HTMLDocumentEvents2_Event iEvent;
iEvent = (mshtml.HTMLDocumentEvents2_Event)doc;
iEvent.onclick += new mshtml.HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);
}
private bool ClickEventHandler(mshtml.IHTMLEventObj e)
{
IHTMLElement button = doc.GetElementFromPoint(e.ClientMousePosition);
return true;
}
Getting these errors;

'mshtml.IHTMLEventObj' does not contain a definition for 'ClientMousePosition' and no extension method
'ClientMousePosition' accepting a first argument of type 'mshtml.IHTMLEventObj' could be found (are you
missing a using directive or an assembly reference?)

'mshtml.HTMLDocument' does not contain a definition for 'GetElementFromPoint' and no extension method
'GetElementFromPoint' accepting a first argument of type 'mshtml.HTMLDocument' could be found (are
you missing a using directive or an assembly reference?)

There must be a way, right?

Regards,

Vincent

Hi Vincent,

As far as I know, the WPF webbrowser control doesn't support this feature currently.

I would recommend you consider hosting a winform webbrowser control with the way shared in
http://msdn.microsoft.com/en-us/library/ms751761(v=vs.110).aspx instead.

Regards.

Carl

We are trying to better understand customer views on social support experience, so your participation in this
interview project would be greatly appreciated if you have time. Thanks for helping make community forums a
great place.
Click HERE to participate the survey.
Edited by Carl Cai Tuesday, August 19, 2014 3:19 AM
Marked as answer by Vincent Gio Tuesday, August 19, 2014 1:40 PM
Unmarked as answer by Vincent Gio Tuesday, August 19, 2014 1:40 PM

Tuesday, August 19, 2014 3:18 AM

Reply | Quote

"

Getting these errors;

'mshtml.IHTMLEventObj' does not contain a definition for 'ClientMousePosition' and no extension method
0 'ClientMousePosition' accepting a first argument of type 'mshtml.IHTMLEventObj' could be found (are you
Sign in
to vote missing a using directive or an assembly reference?)

"

Oh dear.

Well that's the problem with trusting stuff you find on the web.

Someone else's "great solution" lights up like a Christmas tree when you actually paste the thing into vs.

I'm not so keen on using windows controls in wpf as it can be a bit iffy with the aero bug thing.

I think I'd look into using javascript from the page.

Hope that helps


Please don't forget to up vote answers you like or which help you and mark one(s) which answer your question.

Tuesday, August 19, 2014 8:17 AM Moderator

Reply | Quote

"

Getting these errors;

0 'mshtml.IHTMLEventObj' does not contain a definition for 'ClientMousePosition' and no extension method
Sign in 'ClientMousePosition' accepting a first argument of type 'mshtml.IHTMLEventObj' could be found (are you
to vote
missing a using directive or an assembly reference?)

"

Oh dear.

Well that's the problem with trusting stuff you find on the web.

Someone else's "great solution" lights up like a Christmas tree when you actually paste the thing into vs.

I'm not so keen on using windows controls in wpf as it can be a bit iffy with the aero bug thing.

I think I'd look into using javascript from the page.

Hope that helps


Please don't forget to up vote answers you like or which help you and mark one(s) which answer your
question.
So, how would I look into using javascript with the browser?

Tuesday, August 19, 2014 1:40 PM

Reply | Quote

This link has a fair bit of stuff in it.

http://www.codegain.com/articles/wpf/ieprogramming/working-with-webbrowser-in-wpf.aspx

.
0
Sign in The straight forward way is to inject functions into the page header.
to vote
You can attach javascript to the document header as you load it.

That can wait until the dom has loaded. walk the dom and attach a function to every type of control you want to
identify clicks on.

Passing back the control id or whatever.

Attaching a script:

http://stackoverflow.com/questions/153748/how-to-inject-javascript-in-webbrowser-control

HtmlDocument doc = browser.Document;


HtmlElement head = doc.GetElementsByTagName("head")[0];
HtmlElement s = doc.CreateElement("script");
s.SetAttribute("text","function sayhello() { alert('hello'); }");
head.AppendChild(s);
browser.Document.InvokeScript("sayHello");

Walking the dom.

http://www.javascriptcookbook.com/article/Traversing-DOM-subtrees-with-a-recursive-walk-the-DOM-function

You'd use that to identify whatever you are interested in attaching a click to.

http://stackoverflow.com/questions/9800310/add-event-handler-to-html-element-using-javascript

pass the element to the click

http://stackoverflow.com/questions/13893138/javascript-click-event-listener-on-multiple-elements-and-get-
target-id

articles = document.getElementsByTagName('article');
articles.addEventListener('click',redirect,false);
function redirect(e){
alert(e.target.id);
}

And that first link tells you about firing c# methods from javascript.

Hope that helps


Please don't forget to up vote answers you like or which help you and mark one(s) which answer your question.

Edited by Andy ONeill Moderator Tuesday, August 19, 2014 2:20 PM


Marked as answer by Vincent Gio Tuesday, August 19, 2014 6:24 PM

Tuesday, August 19, 2014 2:20 PM Moderator

Reply | Quote
Thank you Andy,

I will look into it for my future development (when I've released a stable build and can focus on that).

For now, I will go with a winforms host for the Browser.


0
Sign in
to vote
Tuesday, August 19, 2014 6:23 PM

Reply | Quote

Probably wise.

Should you go with javascript I suggest you start with an asp.net project and experiment.

Write your javascript into the page to walk the tree and just alert the node ids.
0
Sign in Then refactor to add click with alerts.
to vote
Prove that bit.

Then you can take that javascript out and host that particular web page.

Inject the javascript and prove that works on your page.

Temporarilly switch that off and write a javascript function communicates out that page to you wpf app.

Prove that bit works.

Then do your injecting to the final target page you're after it working with.

Hope that helps


Please don't forget to up vote answers you like or which help you and mark one(s) which answer your question.

Tuesday, August 19, 2014 6:32 PM Moderator

Reply | Quote

© 2018 Microsoft. All rights reserved.


Terms of Use | Trademarks | Privacy Statement | Site Feedback
D /


Sign in

How to: Access the HTML


Source in the Managed HTML
Document Object Model
 2 minutes to read
Contributors all

The DocumentStream and DocumentText properties on the WebBrowser


control return the HTML of the current document as it exised when it was frs
displayed. However, if you modify the page using method and property calls
such as AppendChild and InnerHtml, these changes will not appear when you
call DocumentStream and DocumentText . To obtain the mos up-to-date
HTML source for the DOM, you mus call the OuterHtml property on the
HTML element.

The following procedure shows how to retrieve the dynamic source and
display it in a separate shortcut menu.

Retrieving the dynamic source with the OuterHtml property

1. Create a new Windows Forms application. Start with a single Form, and
call it Form1 .

2. Hos the WebBrowser control in your Windows Forms application, and


name it WebBrowser1 . For more information, see How to: Add Web
Browser Capabilities to a Windows Forms Application.

3. Create a second Form in your application called CodeForm .


4. Add a RichTextBox control to CodeForm and set its Dock property to
Fill .

5. Create a public property on CodeForm called Code .

public sring Code


{
get
{
if (richTextBox1.Text != null)
{
return (richTextBox1.Text);
}
else
{
return ("");
}
}
set
{
richTextBox1.Text = value;
}
}

Public Property Code() As String


Get
If (RichTextBox1.Text IsNot Nothing) Then
Code = RichTextBox1.Text
Else
Code = ""
End If
End Get

Set(ByVal value As String)


RichTextBox1.Text = value
End Set
End Property

6. Add a Button control named Button1 to your Form, and monitor for the
Click event. For details on monitoring events, see Events.

7. Add the following code to the Click event handler.


private void button1_Click(object sender, EventArgs e)
{
HtmlElement elem;

if (webBrowser1.Document != null)
{
CodeForm cf = new CodeForm();
HtmlElementCollection elems =
webBrowser1.Document.GetElementsByTagName("HTML");
if (elems.Count == 1)
{
elem = elems[0];
cf.Code = elem.OuterHtml;
cf.Show();
}
}
}

Private Sub Button1_Click(ByVal sender As Sysem.Object, ByVal e


As Sysem.EventArgs) Handles Button1.Click
Dim elem As HtmlElement

If (WebBrowser1.Document IsNot Nothing) Then


Dim cf As New CodeForm()
Dim elems As HtmlElementCollection =
WebBrowser1.Document.GetElementsByTagName("HTML")
If (elems.Count = 1) Then
elem = elems(0)
cf.Code = elem.OuterHtml
cf.Show()
End If
End If
End Sub

Robus Programming
Always tes the value of Document before attempting to retrieve it. If the
current page is not fnished loading, Document or one or more of its child
objects may not be initialized.

See Also
Using the Managed HTML Document Object Model
WebBrowser Control Overview
Feedback

We'd love to hear your thoughts. Choose the type you'd like to provide:

Product feedback M

6 Sign in to give documentation feedback

Our new feedback sysem is built on GitHub Issues. Read about this change in our blog pos.

Loading feedback...

Previous Version Docs � Blog � Contribute � Privacy & Cookies � Terms of Use � Site Feedback � Trademarks
This site uses cookies for analytics, personalized content and ads. By continuing to browse this site, you agree to this use. Learn more

Developer Network

Search

MSDN Library Print

How to: Add HyperLink Web Server Controls to


a Web Forms Page
Other Versions

You can add a hyperlink to your Web Forms page by placing a HyperLink Web server control on the page and associating it with a URL.
You can specify that HyperLink controls render as either text or as graphics.

To add a HyperLink Web server control to a Web Forms page

1. From the Standard tab of the Toolbox, drag a HyperLink control onto the page.

2. In the Appearance category of the Properties window, specify the format of the link on the page by doing one of the following:

To create a text link, set the control's Text property. You can include HTML formatting in the property. For example, you
can format an individual word in the text as bold by placing a <B> tag around it in the Text property.

To create a graphical link, set the control's ImageUrl property to the URL of a .gif, .jpg, or other Web graphic file.

Note

If you set both the ImageUrl and Text properties, the ImageUrl property takes precedence.

3. In the Navigation category of the Properties window, set the NavigateUrl property to the URL of the page to which you want
to link.

Security Note

The URL that is associated with a hyperlink points to an external resource. If you point to a resource that you do not own, be
sure it is safe for your users to work with. For more information, see Script Exploits Overview.

4. Optionally, in the Navigation category of the Properties window, specify the target by setting the ID of a target window or
frame in which to display the linked page. You can either specify a window by name or use predefined target values, such as
_top, _parent, and so on.

Note

You can change the appearance of the link text — for example, whether it is underlined — by using styles. For details, see
ASP.NET Web Server Controls and CSS Styles.

The following example shows how you can set the properties of a HyperLink control at run time. The method handles a Button
control's Click event and sets the control's link text and target page.

C# VB

protected void Button1_Click (object sender, System.EventArgs e)


{
this.HyperLink1.Text = "Home";
this.HyperLink1.NavigateUrl = "http://www.microsoft.com/net/";
}

See Also
Reference
HyperLink Web Server Control Overview

Is this page helpful? Yes


Yes No
No

Dev centers Learning resources Community


Microsoft Virtual Academy Forums
Windows
Channel 9 Blogs
MSDN Magazine Codeplex
Office

Visual Studio
Support Programs
Self support BizSpark (for startups)
Microsoft Azure
Microsoft Imagine (for students)

More...

United States (English) Newsletter Privacy & cookies Terms of use Trademarks
© 2018 Microsoft
This site uses cookies for analytics, personalized content and ads. By continuing to browse this site, you agree to this use. Learn more

SIGN IN

get started for free


GALLERY MSDN LIBRARY FORUMS

Ask a question Search related threads Search forum questions


Submit

Quick access

Answered by: how to create Hyperlink inside textblock from


codebehind
.NET Framework > Windows Presentation Foundation (WPF)

Question

the xaml code is

<Expander>

<StackPanel>
0
<TextBlock>
Sign in
to vote
<Hyperlink NavigateUri="someurl">hi</Hyperlink>

</TextBlock>

</StackPanel>

</Expander>

i need the same to be done from my code behind.

If i pass the entire Hyperlink tag as Text to textblock its displayed in same tag format.

I tried passing inlines to TextBlock it doesn't work.

Wednesday, September 27, 2006 1:18 AM

Reply | Quote

Answers

you can do

TextBlock t = new TextBlock();

0
Sign in Run ln = new Run("some link");
to vote

t.Inlines.Add(new Hyperlink(ln));

c1.Children.Add(t);(c1 is a canvas)

Wednesday, September 27, 2006 2:13 AM Moderator

Reply | Quote

All replies

you can do

TextBlock t = new TextBlock();

0
Sign in Run ln = new Run("some link");
to vote

t.Inlines.Add(new Hyperlink(ln));

c1.Children.Add(t);(c1 is a canvas)

Wednesday, September 27, 2006 2:13 AM Moderator

Reply | Quote

Thank you

Wednesday, September 27, 2006 4:31 AM

Reply | Quote
0
Sign in
to vote

This may be a stupid question, because I am a XAML newbie, but in the example above, how do you
display the text (i.e - "hi") rather than the uri in the hyperlink from code-behind?

Wednesday, February 20, 2008 6:15 PM


0 Reply | Quote
Sign in
to vote

This may be a stupid question, because I am a XAML newbie, but in the example above, how do you display
the text (i.e - "hi") rather than the uri in the hyperlink from code-behind?

0 HyperLink hl = new HyperLink();


Sign in hl.Inlines.Add(new TextBlock { Text = "hi" });
to vote

Friday, July 8, 2011 3:23 PM


Reply | Quote

DEV CENTERS RELATED SITES CONNECT DEVELOPER RESOURCES

Windows Visual Studio Forums Code samples


Office Visual Studio Integrate Blog Documentation
More... VSIP Program Facebook Downloads
Microsoft .NET LinkedIn Products & extensions for Visual Studio
Microsoft Azure Stack Overflow REST APIs
Twitter Testing tools for web developers
Visual Studio Events Videos and tutorials
YouTube Virtual Labs

United States © 2018 Microsoft Terms of Use Trademarks Privacy Statement Site Feedback
(English)
D /


Sign in

HtmlDocument.GetElement
FromPoint(Point) Html
Document.GetElementFrom
Point(Point) HtmlDocument.Get
ElementFromPoint(Point)
Method
Namespace:
Sysem.Windows.Forms Sysem.Windows.Forms Sysem.Windows.Forms
Assembly:
Sysem.Windows.Forms.dll

Retrieves the HTML element located at the specifed client coordinates.

public:
Sysem::Windows::Forms::HtmlElement ^
GetElementFromPoint(Sysem::Drawing::Point point);

public Sysem.Windows.Forms.HtmlElement GetElementFromPoint


(Sysem.Drawing.Point point);
member this.GetElementFromPoint : Sysem.Drawing.Point ->
Sysem.Windows.Forms.HtmlElement

Parameters
point
Point Point Point
The x,y position of the element on the screen, relative to the top-left corner of
the document.

Returns
HtmlElement HtmlElement HtmlElement
The HtmlElement at the specifed screen location in the document.

Examples
The following code example detects a click on the document, fnds the
element, and uses ScrollIntoView to align the element with the top of the Web
page.

private void Document_Click(Object sender, HtmlElementEventArgs e)


{
if (webBrowser1.Document != null)
{
HtmlElement elem =
webBrowser1.Document.GetElementFromPoint(e.ClientMousePosition);
elem.ScrollIntoView(true);
}
}

Private Sub Document_Click(ByVal sender As Object, ByVal e As


HtmlElementEventArgs)
If (WebBrowser1.Document IsNot Nothing) Then
Dim Elem As HtmlElement =
WebBrowser1.Document.GetElementFromPoint(e.ClientMousePosition)
Elem.ScrollIntoView(True)
End If
End Sub
Remarks
GetElementFromPoint uses client coordinates, in which the upper-left corner of
the document is assigned the value (0,0). Client coordinates for the current
position of the cursor can be obtained using the Position property.

Applies to

See Also
elementFromPoint Method

Feedback

We'd love to hear your thoughts. Choose the type you'd like to provide:

Product feedback M

6 Sign in to give documentation feedback

Our new feedback sysem is built on GitHub Issues. Read about this change in our blog pos.

Loading feedback...

Previous Version Docs � Blog � Contribute � Privacy & Cookies � Terms of Use � Site Feedback � Trademarks
D /


Sign in

HtmlElement HtmlElement Html


Element HtmlElement Class
Namespace:
Sysem.Windows.Forms Sysem.Windows.Forms Sysem.Windows.Forms Sysem.Windows.Forms
Assembly:
Sysem.Windows.Forms.dll

Represents an HTML element inside of a Web page.

public ref class HtmlElement sealed

public sealed class HtmlElement

type HtmlElement = class

Public NotInheritable Class HtmlElement

Inheritance
ObjectObjectObjectObject 9

HtmlElementHtmlElementHtmlElementHtmlElement
Examples
The following code example shows how to examine an arbitrary HTML
document and derive a sring describing the HTML elements, with indentation
and level numbers used to indicate how deeply nesed the elements are in the
document. This code example requires that your application hoss a
WebBrowser control named WebBrowser1 .

private void PrintDomBegin()


{
if (webBrowser1.Document != null)
{
HtmlElementCollection elemColl = null;
HtmlDocument doc = webBrowser1.Document;
if (doc != null)
{
elemColl = doc.GetElementsByTagName("HTML");
String sr = PrintDom(elemColl, new Sysem.Text.StringBuilder(), 0);
webBrowser1.DocumentText = sr;
}
}
}

private sring PrintDom(HtmlElementCollection elemColl,


Sysem.Text.StringBuilder returnStr, Int32 depth)
{
Sysem.Text.StringBuilder sr = new Sysem.Text.StringBuilder();

foreach (HtmlElement elem in elemColl)


{
sring elemName;

elemName = elem.GetAttribute("ID");
if (elemName == null || elemName.Length == 0)
{
elemName = elem.GetAttribute("name");
if (elemName == null || elemName.Length == 0)
{
elemName = "<no name>";
}
}

sr.Append(' ', depth * 4);


sr.Append(elemName + ": " + elem.TagName + "(Level " + depth +
")");
returnStr.AppendLine(sr.ToString());

if (elem.CanHaveChildren)
{
PrintDom(elem.Children, returnStr, depth + 1);
}

sr.Remove(0, sr.Length);
}

return(returnStr.ToString());
}

Private Sub PrintDomBegin()


If (WebBrowser1.Document IsNot Nothing) Then
Dim ElemColl As HtmlElementCollection

Dim Doc As HtmlDocument = WebBrowser1.Document


If (Not (Doc Is Nothing)) Then
ElemColl = Doc.GetElementsByTagName("HTML")
Dim Str As String = PrintDom(ElemColl, New
Sysem.Text.StringBuilder(), 0)

WebBrowser1.DocumentText = Str
End If
End If
End Sub

Private Function PrintDom(ByVal ElemColl As HtmlElementCollection,


ByRef ReturnStr As Sysem.Text.StringBuilder, ByVal Depth As Integer)
As String
Dim Str As New Sysem.Text.StringBuilder()

For Each Elem As HtmlElement In ElemColl


Dim ElemName As String

ElemName = Elem.GetAttribute("ID")
If (ElemName Is Nothing Or ElemName.Length = 0) Then
ElemName = Elem.GetAttribute("name")
If (ElemName Is Nothing Or ElemName.Length = 0) Then
ElemName = "<no name>"
End If
End If

Str.Append(CChar(" "), Depth * 4)


Str.Append(ElemName & ": " & Elem.TagName & "(Level " & Depth
& ")")
ReturnStr.AppendLine(Str.ToString())

If (Elem.CanHaveChildren) Then
PrintDom(Elem.Children, ReturnStr, Depth + 1)
End If

Str.Remove(0, Str.Length)
Next

PrintDom = ReturnStr.ToString()
End Function

Remarks
HtmlElement represents any possible type of element in an HTML document,
such as BODY , TABLE , and FORM , among others. The class exposes the mos
common properties you can expect to fnd on all elements.

Mos elements can have child elements: other HTML elements that are placed
underneath them. Use the CanHaveChildren property to tes whether a given
element has children, and the Children collection to iterate through them. The
Parent property returns the HtmlElement in which the current element is
nesed.

You often need access to attributes, properties, and methods on the


underlying element that are not directly exposed by HtmlElement, such as the
SRC attribute on an IMG element or the Submit method on a FORM . The
GetAttribute and SetAttribute methods enable you to retrieve and alter any
attribute or property on a specifc element, while InvokeMember provides
access to any methods not exposed in the managed Document Object Model
(DOM). If your application has unmanaged code permission, you can also
access unexposed properties and methods with the DomElement attribute.

Use the TagName property to tes whether an element is of a specifc type.

Any HTML document can be modifed at run time. You can create new
HtmlElement objects with the CreateElement method of HtmlDocument, and
add them to another element using the AppendChild or InsertAdjacentElement
methods. You can also create the elements as HTML tags and assign them to
an exising element's InnerHtml property.

Properties
All All All All Gets an HtmlElementCollection of all elements underneath the
current element.

CanHaveChildren Gets a value indicating whether this element can have child
CanHaveChildren elements.
CanHaveChildren
CanHaveChildren

Children Children Gets an HtmlElementCollection of all children of the current


Children Children element.

ClientRectangle Gets the bounds of the client area of the element in the HTML
ClientRectangle document.
ClientRectangle
ClientRectangle

Document Document Gets the HtmlDocument to which this element belongs.


Document Document

DomElement Gets an unmanaged interface pointer for this element.


DomElement
DomElement
DomElement

Enabled Enabled Gets or sets whether the user can input data into this element.
Enabled Enabled

FirsChild FirsChild Gets the next element below this element in the document tree.
FirsChild FirsChild

Id Id Id Id Gets or sets a label by which to identify the element.

InnerHtml InnerHtml Gets or sets the HTML markup underneath this element.
InnerHtml InnerHtml

InnerText InnerText Gets or sets the text assigned to the element.


InnerText InnerText

Name Name Name Gets or sets the name of the element.


Name

NextSibling NextSibling Gets the next element at the same level as this element in the
NextSibling NextSibling document tree.

OfsetParent Gets the element from which OfsetRectangle is calculated.


OfsetParent
OfsetParent
OfsetParent

OfsetRectangle Gets the location of an element relative to its parent.


OfsetRectangle
OfsetRectangle
OfsetRectangle

OuterHtml OuterHtml Gets or sets the current element's HTML code.


OuterHtml OuterHtml

OuterText OuterText Gets or sets the current element's text.


OuterText OuterText

Parent Parent Parent Gets the current element's parent element.


Parent

ScrollLeft ScrollLeft Gets or sets the disance between the edge of the element and the
ScrollLeft ScrollLeft left edge of its content.

ScrollRectangle Gets the dimensions of an element's scrollable region.


ScrollRectangle
ScrollRectangle
ScrollRectangle

ScrollTop ScrollTop Gets or sets the disance between the edge of the element and the
ScrollTop ScrollTop top edge of its content.

Style Style Style Style Gets or sets a semicolon-delimited lis of syles for the current
element.

TabIndex TabIndex Gets or sets the location of this element in the tab order.
TabIndex TabIndex

TagName TagName Gets the name of the HTML tag.


TagName TagName

Methods
AppendChild(HtmlElement) Adds an element to another element's subtree.
AppendChild(HtmlElement)
AppendChild(HtmlElement)
AppendChild(HtmlElement)

AttachEventHandler(String, Adds an event handler for a named event on the HTML Document
EventHandler) Object Model (DOM).
AttachEventHandler(String,
EventHandler)
AttachEventHandler(String,
EventHandler)
AttachEventHandler(String,
EventHandler)

DetachEventHandler(String, Removes an event handler from a named event on the HTML


EventHandler) Document Object Model (DOM).
DetachEventHandler(String,
EventHandler)
DetachEventHandler(String,
EventHandler)
DetachEventHandler(String,
EventHandler)

Equals(Object) Tess if the supplied object is equal to the current element.


Equals(Object)
Equals(Object)
Equals(Object)

Focus() Focus() Focus() Puts user input focus on the current element.
Focus()

GetAttribute(String) Retrieves the value of the named attribute on the element.


GetAttribute(String)
GetAttribute(String)
GetAttribute(String)

GetElementsByTagName(String)
Retrieves a collection of elements represented in HTML by the
GetElementsByTagName(String)
specifed HTML tag.
GetElementsByTagName(String)
GetElementsByTagName(String)

GetHashCode() Serves as a hash function for a particular type.


GetHashCode()
GetHashCode()
GetHashCode()

GetType() GetType() Gets the Type of the current insance.


GetType() GetType() (Inherited from Object)

InsertAdjacentElement(HtmlElementInsertionOrientation,
Insert a new element into the Document Object Model (DOM).
HtmlElement)
InsertAdjacentElement(HtmlElementInsertionOrientation,
HtmlElement)
InsertAdjacentElement(HtmlElementInsertionOrientation,
HtmlElement)
InsertAdjacentElement(HtmlElementInsertionOrientation,
HtmlElement)

InvokeMember(String) Executes an unexposed method on the underlying DOM element of


InvokeMember(String) this element.
InvokeMember(String)
InvokeMember(String)

InvokeMember(String, Executes a function defned in the current HTML page by a scripting


Object[]) language.
InvokeMember(String,
Object[])
InvokeMember(String,
Object[])
InvokeMember(String,
Object[])

MemberwiseClone() Creates a shallow copy of the current Object.


MemberwiseClone() (Inherited from Object)
MemberwiseClone()
MemberwiseClone()

RaiseEvent(String) Causes the named event to call all regisered event handlers.
RaiseEvent(String)
RaiseEvent(String)
RaiseEvent(String)

RemoveFocus() Removes focus from the current element, if that element has focus.
RemoveFocus()
RemoveFocus()
RemoveFocus()

ScrollIntoView(Boolean) Scrolls through the document containing this element until the top
ScrollIntoView(Boolean) or bottom edge of this element is aligned with the document's
ScrollIntoView(Boolean) window.
ScrollIntoView(Boolean)

SetAttribute(String, Sets the value of the named attribute on the element.


String)
SetAttribute(String,
String)
SetAttribute(String,
String)
SetAttribute(String,
String)
ToString() ToString() Returns a sring that represents the current object.
ToString() ToString() (Inherited from Object)

Events
Click Click Click Click Occurs when the user clicks on the element with the left mouse
button.

DoubleClick Occurs when the user clicks the left mouse button over an element
DoubleClick twice, in rapid succession.
DoubleClick
DoubleClick

Drag Drag Drag Drag Occurs when the user drags text to various locations.

DragEnd DragEnd Occurs when a user fnishes a drag operation.


DragEnd DragEnd

DragLeave DragLeave Occurs when the user is no longer dragging an item over this
DragLeave DragLeave element.

DragOver DragOver Occurs when the user drags text over the element.
DragOver DragOver

Focusing Focusing Occurs when the element frs receives user input focus.
Focusing Focusing

GotFocus GotFocus Occurs when the element has received user input focus.
GotFocus GotFocus

KeyDown KeyDown Occurs when the user presses a key on the keyboard.
KeyDown KeyDown

KeyPress KeyPress Occurs when the user presses and releases a key on the keyboard.
KeyPress KeyPress

KeyUp KeyUp KeyUp Occurs when the user releases a key on the keyboard.
KeyUp

LosingFocus Occurs when the element is losing user input focus.


LosingFocus
LosingFocus
LosingFocus

LosFocus LosFocus Occurs when the element has los user input focus.
LosFocus LosFocus

MouseDown Occurs when the user presses a mouse button.


MouseDown
MouseDown
MouseDown

MouseEnter Occurs when the user frs moves the mouse cursor over the current
MouseEnter element.
MouseEnter
MouseEnter

MouseLeave Occurs when the user moves the mouse cursor of of the current
MouseLeave element.
MouseLeave
MouseLeave

MouseMove Occurs when the user moves the mouse cursor across the element.
MouseMove
MouseMove
MouseMove

MouseOver Occurs when the mouse cursor enters the bounds of the element.
MouseOver
MouseOver
MouseOver

MouseUp MouseUp Occurs when the user releases a mouse button.


MouseUp MouseUp

Operators
Equality(HtmlElement, Compares two elements for equality.
HtmlElement)
Equality(HtmlElement,
HtmlElement)
Equality(HtmlElement,
HtmlElement)
Equality(HtmlElement,
HtmlElement)
Inequality(HtmlElement, Compares two HtmlElement objects for inequality.
HtmlElement)
Inequality(HtmlElement,
HtmlElement)
Inequality(HtmlElement,
HtmlElement)
Inequality(HtmlElement,
HtmlElement)

Applies to

See Also
IHTMLElement Interface
IHTMLElement2 Interface
IHTMLElement3 Interface
IHTMLElement4 Interface

Feedback

We'd love to hear your thoughts. Choose the type you'd like to provide:

Product feedback M

6 Sign in to give documentation feedback

Our new feedback sysem is built on GitHub Issues. Read about this change in our blog pos.

Loading feedback...

Previous Version Docs � Blog � Contribute � Privacy & Cookies � Terms of Use � Site Feedback � Trademarks
C# Corner

Hyperlink In WPF

Mahesh Chand Oct 04 2018 Article

6 0 149.5k

The Hyperlink element is an inline-level content element that is used to add a hyperlink to a FlowDocument contents. You
can add hyperlink support to any Inline element.

Hyperlink is defined in System.Windows.Documents namespace. You must import this namespace before you use
Hyperlink.

Here is the Italic syntax for Hyperlink.

01. <Hyperlink>  
02.    Inlines  
03. </Hyperlink >  

Here is an example of hyperlink that sets NavigateUri to C# Corner website URL.

01. <Hyperlink NavigateUri="http://www.c-sharpcorner.com">  


02.    C# Corner  
03. </Hyperlink>  

Listing 1 is a complete example that shows how to use a Hyperlink element in FlowDocument contents.

01. <FlowDocument ColumnWidth="400" IsOptimalParagraphEnabled="True" IsHyphenationEnabled="True">  


02.     <Section Name="Heading" FontSize="20" FontFamily="Georgia" Background="LightSalmon">  
03.         <Paragraph> Hyperlink sample </Paragraph>  
04.     </Section>  
05.     <Section FontSize="12">  
06.         <Paragraph>  
07.             <Bold>Mindcracker Network</Bold> including <Bold>  
08.                 <Hyperlink NavigateUri="http://www.c-sharpcorner.com"> C# Corner </Hyperlink>  
09.             </Bold> is an online community for Software developers and profressioals. Mindcracker Network                    
</Bold> It also allows members to ask and reply questions on <Bold>Mindcracker Forums.</Bold>  
10.             <Floater Background="GhostWhite" Width="285" HorizontalAlignment="Left">  
11.                 <Table CellSpacing="5">  
12.                     <Table.Columns>  
13.                         <TableColumn Width="155" />  
14.                         <TableColumn Width="130" />  
15.                     </Table.Columns>  
16.                     <TableRowGroup>  
17.                         <TableRow>  
18.                             <TableCell ColumnSpan="3" Background="LightBlue" FontSize="16">  
19.                                 <Paragraph>Mindcracker Statistics</Paragraph>  
20.                             </TableCell>  
21.                         </TableRow>  
22.                         <TableRow Background="LightGoldenrodYellow" FontSize="11">  
23.                             <TableCell>  
24.                                 <Paragraph FontWeight="Bold">Monthly Page views:</Paragraph>  
25.                             </TableCell>  
26.                             <TableCell>  
27.                                 <Paragraph>3.8 Million</Paragraph>  
28.                             </TableCell>  
29.                         </TableRow>  
30.                         <TableRow FontSize="11" Background="LightGray">  
31.                             <TableCell>  
32.                                 <Paragraph FontWeight="Bold">Monthly Unique Visitors:</Paragraph>  
33.                             </TableCell>  
34.                             <TableCell>  
35.                                 <Paragraph>2.3 Million</Paragraph>  
36.                             </TableCell>  
37.                         </TableRow>  
38.                         <TableRow Background="LightGoldenrodYellow" FontSize="11">  
39.                             <TableCell>  
40.                                 <Paragraph FontWeight="Bold">US Visitors:</Paragraph>  
41.                             </TableCell>  
42.                             <TableCell>  
43.                                 <Paragraph>43%</Paragraph>  
44.                             </TableCell>  
45.                         </TableRow>  
46.                         <TableRow>  
47.                             <TableCell ColumnSpan="4">  
48.                                 <Paragraph FontSize="10" FontStyle="Italic"> View more details on <Hyperl
sharpcorner.com/forums/"> Mindcracker Network. </Hyperlink>  
49.                                 </Paragraph>  
50.                             </TableCell>  
51.                         </TableRow>  
52.                     </TableRowGroup>  
53.                 </Table>  
54.             </Floater>  
55.         </Paragraph>  
56.     </Section>  
57. </FlowDocument>  

Listing 1

The output of Listing 1 looks like Figure 1.


Figure 1

Dynamic Hyperlink

The Hyperlink class in WPF is used to add a hyperlink to a FlowDocument. The code snippet in Listing 1 creates a
hyperlink dynamically.

01. privateFlowDocument CreateAHyperlinkDynamically() {  


02.     // Create a FlowDocument  
03.     FlowDocument doc = newFlowDocument();  
04.     // Create a Paragraph and 3 Runs  
05.     Paragraph p = newParagraph();  
06.     Run run1 = newRun("Hyperlink Sample ");  
07.     Run run2 = newRun(" Hyperlink added");  
08.     Run run3 = newRun("C# Corner ");  
09.     // Create a Hyperlink and set NavigateUri  
10.     Hyperlink hlink = newHyperlink(run3);  
11.     hlink.NavigateUri = newUri("http://www.c-sharpcorner.com");  
12.     // Add Runs and Hyperlink to Paragraph  
13.     p.Inlines.Add(run1);  
14.     p.Inlines.Add(hlink);  
15.     p.Inlines.Add(run2);  
16.     // Add Paragraph to FlowDocument  
17.     doc.Blocks.Add(p);  
18.     return doc;  
19. }  

Listing 1

Hyperlink in WPF Link in WPF WPF WPF hyperlink


Philadelphia
New York
London
Delhi
Join C# Corner
and millions of developer friends worldwide.
Enter your email address Sign Up
earn ASP.NET MVC
earn ASP.NET Core
earn Python
earn JavaScript
earn Xamarin
earn Oracle
ore...
ome
onsultants
obs
areer Advice
ories
artners
# Tutorials

About Us Contact Us Privacy Policy Terms Media Kit Sitemap Report a Bug FAQ
©2018 C# Corner. All contents are copyright of their authors.
Installing And Using An XML/SGML DocBook Editing Suite
Setting Up A Free XML/SGML DocBook Editing Suite For Windows And
Unix/Linux/BSD
Ashley J.S Mills
<[email protected]>

Copyright (c) 2002 The University Of Birmingham

Revision History
Revision 0.8 03/07/2002
Alpha Release
Revision 0.8 12/07/2002
Beta1 Release
Revision 0.9 22/07/2002
Beta2 Release
Revision 1.0 13/10/02
First real release

Table of Contents

I. Setting Up Your System To Author DocBook Documents

1. Introduction

1.1. Introduction
1.2. SGML vs XML
1.3. Preliminary Requirements
1.4. About this guide

2. Installing And Configuring An SGML DocBook Authoring System For Windows

2.1. Overview Of Required Tools


2.2. Setting Up Environment Variables
2.3. Install OpenJade

2.3.1. Windows
2.3.2. Unix/Linux/BSD

2.4. Setup SGML_CATALOG_FILES environment variable


2.5. Install The SGML DocBook DTD
2.6. Install The ISO-Entities
2.7. Install The SGML DocBook Stylesheets
2.8. Install TeX

2.8.1. Windows
2.8.2. Unix/Linux/BSD

2.9. Install JadeTeX


2.10. Install Ghostscript and GhostView

2.10.1. Windows
2.10.2. Unix/Linux/BSD

2.11. Install The Custom Style-Sheets

3. Installing And Configuring An XML DocBook System For Windows

3.1. Introduction
3.2. Installing the JAVA Runtime Environment
3.3. libxml

3.3.1. Windows
3.3.2. Linux/Unix/BSD

3.4. Install Saxon

3.4.1. Setup Catalog Resolver

3.5. FOP

3.5.1. Install Jimi

3.6. DocBook DTD

3.6.1. Catalog Files

3.7. XSL StyleSheets

3.7.1. Custom StyleSheets

4. Using The SGML Tools

4.1. About this chapter


4.2. Validating an SGML DocBook Document with onsgmls
4.3. Using OpenJade to convert SGML DocBook source to an intermediate TeX format
4.4. Using OpenJade to convert SGML DocBook source to (single file)HTML
4.5. Using OpenJade to convert SGML DocBook source to (Chunked) HTML
4.6. Using openjade to convert SGML DocBook source to RTF
4.7. Using jadetex to convert (openjade created) TeX to DVI
4.8. Using JadeTeX to convert (openjade created)TeX to PDF
4.9. Using dvipsto convert DVI to PS
4.10. Using osx to convert SGML DocBook source to an XML tree
4.11. Using the custom DSSSL stylesheets

5. Using the XML Tools

5.1. About this chapter


5.2. Using xmllint to validate an XML DocBook document
5.3. Using xsltproc to generate (Single file)XHTML output from an XML Docbook document
5.4. Using xsltproc to generate XHTML(Segmented) output from an XML Docbook document
5.5. Using xsltproc to generate FO output from an XML Docbook document
5.6. Using xsltproc to generate HTMLhelp output from XML Docbook source
5.7. Using xsltproc to generate Javahelp output from XML Docbook source
5.8. Using Saxon to generate (Single file) HTML output from XML DocBook source
5.9. Using Saxon to generate (Single file) XHTML output from XML DocBook source
5.10. Using Saxon to generate FO output from XML Docbook source
5.11. Using FOP to generate PDF output from XSL FO input
5.12. Using pdfxmltex to generate PDF output from XSL FO input
5.13. General Usage

6. Using The SGML Tools To Process XML DocBook Documents

6.1. About This Chapter


6.2. Using onsgsmls to validate XML DocBook documents
6.3. Using openjade to convert XML DocBook to (segmented) HTML
6.4. Using openjade to convert XML DocBook to (single file) HTML
6.5. Using openjade to convert from XML DocBook to intermediate TeX format
6.6. Using openjade to convert from XML DocBook to RTF
6.7. Using jadetex to convert from (openjade created) intermediate TeX format to DVI
6.8. Using JadeTeX to convert (openjade created)TeX to PDF
6.9. Using dvips to convert from DVI to PS

II. Introduction To Authoring DocBook Documents

7. Creating An SGML DocBook Document

7.1. Declaring the document type


7.2. The use of PUBLIC identifiers in SGML
7.3. The use of SYSTEM identifiers in SGML
7.4. An SGML DocBook article template
7.5. An SGML DocBook book template

8. Creating an XML DocBook document

8.1. Declaring The Document Type


8.2. The use of PUBLIC and SYSTEM identifiers in XML
8.3. Creating an XML DocBook document

8.3.1. An article template


8.3.2. An example XML DocBook Book

9. DocBook Document Examples

9.1. Common DocBook Elements

9.1.1. <para>
9.1.2. <programlisting>
9.1.3. Entities for special characters
9.1.4. <screen>
9.1.5. <ulink>
9.1.6. Lists

9.1.6.1. <itemizedlist>
9.1.6.2. <orderedlist>

9.1.7. Some common inline elements

9.2. Including Images


9.3. Tables

10. Auxiliary Tools for DocBook Authoring

10.1. Editors

10.1.1. VI/VIM/GVIM
10.1.2. Emacs
10.1.3. ThotBook
10.1.4. EpcEdit
10.1.5. Xeena
10.1.6. The rest

10.2. Spell Checking

10.2.1. Aspell
11. References

11.1. Internet Resources Used

List of Figures

9.1. Table frame types


9.2. Table alignment types
9.3. morerows example
9.4. Column spanning example
10.1. GVIM screen-shot
10.2. Emacs screen-shot
10.3. ThotBook screen-shot
10.4. EpcEdit screen-shot
10.5. Xeena screen-shot
10.6. Aspell screen-shot

Setting Up Your System To Author DocBook Documents


Table of Contents

1. Introduction

1.1. Introduction
1.2. SGML vs XML
1.3. Preliminary Requirements
1.4. About this guide

2. Installing And Configuring An SGML DocBook Authoring System For Windows

2.1. Overview Of Required Tools


2.2. Setting Up Environment Variables
2.3. Install OpenJade

2.3.1. Windows
2.3.2. Unix/Linux/BSD

2.4. Setup SGML_CATALOG_FILES environment variable


2.5. Install The SGML DocBook DTD
2.6. Install The ISO-Entities
2.7. Install The SGML DocBook Stylesheets
2.8. Install TeX

2.8.1. Windows
2.8.2. Unix/Linux/BSD

2.9. Install JadeTeX


2.10. Install Ghostscript and GhostView

2.10.1. Windows
2.10.2. Unix/Linux/BSD

2.11. Install The Custom Style-Sheets

3. Installing And Configuring An XML DocBook System For Windows

3.1. Introduction
3.2. Installing the JAVA Runtime Environment
3.3. libxml

3.3.1. Windows
3.3.2. Linux/Unix/BSD

3.4. Install Saxon

3.4.1. Setup Catalog Resolver

3.5. FOP

3.5.1. Install Jimi

3.6. DocBook DTD

3.6.1. Catalog Files

3.7. XSL StyleSheets

3.7.1. Custom StyleSheets

4. Using The SGML Tools

4.1. About this chapter


4.2. Validating an SGML DocBook Document with onsgmls
4.3. Using OpenJade to convert SGML DocBook source to an intermediate TeX format
4.4. Using OpenJade to convert SGML DocBook source to (single file)HTML
4.5. Using OpenJade to convert SGML DocBook source to (Chunked) HTML
4.6. Using openjade to convert SGML DocBook source to RTF
4.7. Using jadetex to convert (openjade created) TeX to DVI
4.8. Using JadeTeX to convert (openjade created)TeX to PDF
4.9. Using dvipsto convert DVI to PS
4.10. Using osx to convert SGML DocBook source to an XML tree
4.11. Using the custom DSSSL stylesheets

5. Using the XML Tools

5.1. About this chapter


5.2. Using xmllint to validate an XML DocBook document
5.3. Using xsltproc to generate (Single file)XHTML output from an XML Docbook document
5.4. Using xsltproc to generate XHTML(Segmented) output from an XML Docbook document
5.5. Using xsltproc to generate FO output from an XML Docbook document
5.6. Using xsltproc to generate HTMLhelp output from XML Docbook source
5.7. Using xsltproc to generate Javahelp output from XML Docbook source
5.8. Using Saxon to generate (Single file) HTML output from XML DocBook source
5.9. Using Saxon to generate (Single file) XHTML output from XML DocBook source
5.10. Using Saxon to generate FO output from XML Docbook source
5.11. Using FOP to generate PDF output from XSL FO input
5.12. Using pdfxmltex to generate PDF output from XSL FO input
5.13. General Usage

6. Using The SGML Tools To Process XML DocBook Documents

6.1. About This Chapter


6.2. Using onsgsmls to validate XML DocBook documents
6.3. Using openjade to convert XML DocBook to (segmented) HTML
6.4. Using openjade to convert XML DocBook to (single file) HTML
6.5. Using openjade to convert from XML DocBook to intermediate TeX format
6.6. Using openjade to convert from XML DocBook to RTF
6.7. Using jadetex to convert from (openjade created) intermediate TeX format to DVI
6.8. Using JadeTeX to convert (openjade created)TeX to PDF
6.9. Using dvips to convert from DVI to PS

Chapter�1.�Introduction
Table of Contents

1.1. Introduction
1.2. SGML vs XML
1.3. Preliminary Requirements
1.4. About this guide

1.1.�Introduction
DocBook is a DTD (Document Type Definition) defined in either SGML (Standard Generalised Markup Language) or XML
(Extensible Markup Language). HTML (Hypertext Markup Language) is another DTD defined in SGML. The DTD specifies how
certain components of the language should be interpreted for example:

<html>
<head><title>HelloWorld</title></head>
<body>
<p>
<b>Hello World!</b>
</p>
</body>
<html>

HTML must start with a head element containing the title element.

The text "Hello World" is encased in bold tags, which are allowed within the <p> tag.

DocBook is a DTD particularly suited to technical writing but it is not limited to it. One of the advantages of using DocBook as
apposed to using some other text processing system is that DocBook can be converted into many other formats. DocBook's popularity
is increasing but it has already been used in many documentation projects such as:

The FreeBSD Documentation Project

The KDE Documentation Project

The GNOME Documentation Project

The Debian Documentation Project

The Darwin Documentation Project

The Linux Documentation Project

The PHP Documentation Project

1.2.�SGML vs XML
The DocBook DTD has been defined in both XML and SGML, it is possible to author DocBook documents using either format and
produce identical results. SGML is the grand-daddy of all markup languages, XML is a subset of SGML with an intent on being the
format for use on the Internet. XML attempts to fill the gap between SGML, which can be used for just about anything, and HTML
which is severely limited and currently being abused because of this. The idea is that XML will be a universal way to mark up
documents so that just-in-time conversion to XHTML can occur and so that information can be exchanged over the Internet in a
standard format. For more about the use of XML and the future of the Internet see XML, Java, and the future of the Web;
http://www.ibiblio.org/pub/sun-info/standards/xml/why/xmlapps.htm

There is much debate about the virtues of XML over SGML and vice-versa. This tutorial will outline both XML DocBook and SGML
DocBook. It has been announced that DocBook 5.0 will be XML compliant, this does not mean that one will have to stop using SGML
DocBook just that if one wants the latest support and integration with the latest technologies, one will have to make the switch
sometime. I suggest that new users go straight to XML and ignore the SGML stuff.

Note

The markup of DocBook with SGML and XML is almost identical, it does not take much effort to switch to
authoring from one to the other. For more information about XML and SGML see http://www.ucc.ie/xml/ and
http://www.oasis-open.org/cover/general.html respectively, for a comparison see http://www.w3.org/TR/NOTE-
sgml-xml.

1.3.�Preliminary Requirements
In order to understand what is going on in this tutorial one should browse this section to get a brief idea of how the components of the
DocBook system interact. An SGML/XML document starts with the DOCTYPE declaration, it looks like this:

<!DOCTYPE name FORMALID "Owner//Keyword Description//Language" >,

This tells the SGML/XML manipulation tools the DTD in use. Where name is the name of the root element in the document, i.e. the
tag that encompasses the rest of the document, the tags allowed by a specific DTD are specified therein. FORMALID is replaced with
either PUBLIC or SYSTEM identifier or both. PUBLIC identifiers identify the DTD that the document conforms to. SYSTEM
identifiers explicitly state the location of the DTD used in the document by means of a URI (Uniform Resource Indicator). PUBLIC
and SYSTEM IDs are usually both present in the DOCTYPE declaration. See Public Identifiers, System Identifiers, and Catalog Files

One could write a DocBook document according to the DocBook DTD and then one could use SGML/XML tools to validate and
convert the document to other formats. Generally conversion requires that we apply a stylesheet, stylesheets are written in languages
such as DynaText, Panorama, SPICE, JSSS, FOSI,CSS and DSSSL. Stylesheets describe how the source document should be
transformed to the respective output formats.

SGML DocBook uses DSSSL (Document Style Semantics and Specification Language), XML DocBook uses XSL (Extensible
Stylesheet Language) HTML uses CSS (Cascading Style Sheets). The stylesheet defines how certain elements should look when
converted to various formats, for instance, one may wish that, when converted to HTML, each sub section of the document should be
displayed in Bold 20 point Times New Roman font and that when converted to PostScript each sub section should be displayed in
some other font. The stylesheet defines how the converted DocBook document will look.

For more information see the reference page and checkout the DocBook FAQ: http://www.dpawson.co.uk/docbook/

1.4.�About this guide


The intent of this document is to provide a set of generic instructions that should enable the average computer user to set up a system
for authoring SGML DocBook and/or XML documents. A key resource for getting going with DocBook is DocBook: The Definitive
guide by Norman Walsh, http://www.docbook.org/tdg/en/html/docbook.html This is definitely a recommended read.

There are already many guides on the Internet which describe how to set up systems for authoring DocBook in XML/SGML and is is
advised that one browses these as well in order to get a more comprehensive view of what is going on and how all the system
components are interacting, if it is suggested that you should read something, it is probably worth while to do so, but hopefully this
guide should be enough to get you started.

Other tutorials for setting up DocBook or authoring with DocBook:

http://ourworld.compuserve.com/homepages/hoenicka_markus/ntsgml.html.

SGML�for�Windows�NT
Setting�up�a�free�SGML/XML�editing�and�publishing�system�on�the�Windows�platform
Markus�Hoenicka
����������

Mark Galassi's http://nis-www.lanl.gov/~rosalia/mydocs/docbook-intro.html


Get�Going�With�DocBook
Notes�for�Hackers
Mark�Galassi
Cygnus�Solutions

Copyright�1998�by�Mark�Galassi
����������

http://www.tldp.org/LDP/LDP-Author-Guide/

LDP�Author�Guide
Mark�F.�Komarinski
Jorge�Godoy
David�C.�Merrill
����������

http://www.bureau-cornavin.com/opensource/crash-course/index.html

Writing�Documentation�Using�DocBook
A�Crash�Course
David�Rugge
Mark�Galassi
Eric�Bischoff
����������

More useful web pages can be found in the reference page.

Chapter�2.�Installing And Configuring An SGML DocBook Authoring System


For Windows
Table of Contents

2.1. Overview Of Required Tools


2.2. Setting Up Environment Variables
2.3. Install OpenJade

2.3.1. Windows
2.3.2. Unix/Linux/BSD

2.4. Setup SGML_CATALOG_FILES environment variable


2.5. Install The SGML DocBook DTD
2.6. Install The ISO-Entities
2.7. Install The SGML DocBook Stylesheets
2.8. Install TeX

2.8.1. Windows
2.8.2. Unix/Linux/BSD

2.9. Install JadeTeX


2.10. Install Ghostscript and GhostView

2.10.1. Windows
2.10.2. Unix/Linux/BSD

2.11. Install The Custom Style-Sheets

2.1. Overview Of Required Tools



OpenJade ; for validating and converting SGML files.

TexLive ; for the JadeTeX and PdfJadeTeX macro packs.

ISO-Entities ; These are required to use the DocBook DTD properly.

The DocBook DTD ; The actual definition of DocBook, used to validate SGML Docbook sources.

The DocBook DSSSL Stylesheets and Documentation ; The stylesheets, specifies how to render SGML DocBook source to
various output formats.

GhostScript ; Used to manipulate PostScript files.

GhostView ; Used to view PostScript files.

2.2.�Setting Up Environment Variables


This installation requires a basic understanding of the target operating system, an understanding of how to change the operating
environment etc. This is covered this in documents entitled Configuring A Windows Working Environment and Configuring A Unix
Working Environment.

Note

This installation uses the notation "/path/to/where/you/installed/program" to refer to the location the program was
installed at, forward slashes are always used but for Windows systems these should be replaced with backslashes
and prefixed with "c:".

2.3.�Install OpenJade
Quoting the website http://www.jclark.com/jade/: “Jade is an implementation of the DSSSL style language”. Jade stands for James'
DSSSL Engine. Openjade is the continuation of the work started by James Clark, the "Open" bit distinguishes it from the original Jade
written by James. More information about OpenJade can be found here: http://openjade.sourceforge.net/.

OpenJade provides some of the tools required to validate and convert SGML DocBook files to other formats. The first step is to install
OpenJade; download a distribution and do what ever is necessary to install the software.

2.3.1.�Windows

Download the latest version of OpenJade from http://sourceforge.net/projects/openjade/, follow the link to OpenJade and then
download the most recent distribution that contains the string "bin" this indicates the windows binaries, the file needed should look
something like this:
openjade-1_3_1-2-bin.zip

Note

The version number may be different, depending on how recently updated this document is.

Unzip the archive to a suitable location.

Append /path/to/where/you/unzipped/openjade/bin to the PATH environment variable.

2.3.2.�Unix/Linux/BSD

Get the latest openjade rpm for your Unix/Linux/BSD distribution from http://rpmfind.net/, install the rpm:
rpm -ivh xxx.rpm (for an install)
rpm -Uvh xxx.rpm (for an upgrade)

Here is a page which goes into RPM in more detail: http://www.linux-mandrake.com/en/howtos/mdk-rpm/.

Alternatively, download the source from http://sourceforge.net/projects/openjade/ and build it in the manner specified in the installation
instructions that come with the file. The default installation directory for openjade is (probably) /usr/local/share/sgml.

2.4.�Setup SGML_CATALOG_FILES environment variable


Catalog files provide the means to map a PUBLIC or SYSTEM identifier in a DOCTYPE declaration to a DTD (Document Type
Definition), note that one may use a catalog file to redirect a SYSTEM identifier. One may exploit and include the official PUBLIC
and SYSTEM identifiers of the DOCTYPE in the declaration yet have these mapped to a local copy of the DTD, this enables one to
represent the DOCTYPE consistently across multiple machines. The environment variable SGML_CATALOG_FILES specifies the location
of the catalog file or files.

Note

It is not obligatory to define the location of catalog files via environment variables, openjade allows, by means of
the -c option, the user to specify where the catalog files can be found at runtime. This can be useful for overriding
catalog files.

An example catalog file entry is shown below:

PUBLIC "-//OASIS//DTD DocBook V4.1//EN" "docbook.dtd"

Which states that any document that has the PUBLIC ID shown above conforms to the DTD specified by the second parameter. If one
does not setup SGML_CATALOG_FILES correctly or does not provide a catalog file to use, when using onsgmls (used to validate SGML
files), one will get an error similar to this:

onsgmls:somefile.sgml:1:57:W: cannot generate system identifier for public text "-//OASIS//DTD


DocBook V4.1//EN"

Create a new environment variable called SGML_CATALOG_FILES in the local environment section. Set it to:
./catalog;/path/to/where/you/unzipped/openjade/dsssl/catalog

./catalog ensures that the working directory is included in the catalog file list so if that one may override a catalog file locally if one
needs to.

2.5.�Install The SGML DocBook DTD


In order to use SGML DocBook one needs a copy of the SGML DocBook DTD. This can be obtained from http://www.oasis-
open.org/docbook/sgml/4.1/ Download.

Download the zip archive http://www.oasis-open.org/docbook/sgml/4.1/docbk41.zip and unzip it to some suitable location. Append
/path/to/where/you/unzipped/docbk41/docbook.cat to the SGML_CATALOG_FILES environment variable.

2.6.�Install The ISO-Entities


One must install the ISO Entities: http://www.oasis-open.org/cover/ISOEnts.zip. The DocBook catalog file references these files, a
normal installation seems to produce an error, this is because the format of the ISO entities is not the same as specified in the DocBook
catalog file, for example docbook.cat says:
PUBLIC "-ISO 8879:1986//ENTITIES Diacritical Marks//EN" "iso-dia.gml"

But this file is actually called ISOdia. In order to fix this I moved these ISO entities and placed them in the same directory as my
DocBook DTD and renamed them so they coordinated with the DocBook catalog file, this solved the error messages produced by
onsgmls. One could alternatively change the entries in the catalog file to point to the actual files on the system.

2.7.�Install The SGML DocBook Stylesheets


To render ones SGML DocBook sources to other file formats one must install stylesheets in order to specify how this rendering is
done. Norman Walsh has produced an excellent set of stylesheets to be used with SGML DocBook, these can be obtained from
http://sourceforge.net/project/showfiles.php?group_id=21935

Download the latest zip version of the file (currently docbook-dsssl-1.76.zip) and unzip it to some suitable directory.

2.8.�Install TeX
2.8.1.�Windows

TeX is a powerful typesetting system created by Donald Knuth of Stanford University. It is used to produce high-quality technical
books and papers. TeX is particularly good at handling complex mathematical expressions. There is a macro package for TeX known
as JadeTeX which provides the ability to convert TeX outputted by other formatting tools from SGML DocBook sources to PDF and
PostScript.

TeXLive is an excellent all-in-one TeX package, download the installation program from here:
ftp://ftp.dante.de/pub/fptex/current/TeXSetup.exe, execute the program and follow the instructions making sure to install the program
in a suitable loaction. Install the Generic recommend TeXLive scheme but check the box that says “I want to customize the selected
scheme”. Select the package tex-htmlxml because this includes the JadeTeX macros. Also select tex-extrabin, tex-fontbin, tex-
fontsextra, tex-mathextra, tex-psfonts and tex-psutils.

Note

During the TeXLive setup, when on the Root of installation page, to avoid later problems, only to change the
“Root directory” field (the others will update automatically), leave the Extra TeXMF tree and Home TeXMF Tree
alone. In other words, do not check the box that says “You can change the default configuration for the main
directories.”.

2.8.2.�Unix/Linux/BSD

There are a number of schools of thought on which is the best TeX distribution to install. A good one is TeXLive unfortunately the
Unix distribution only comes on CDROM, this is ok, as the CDROM is available free and can be downloaded as an ISO-Image to be
burned. An alternative is teTeX whose homepage is http://www.tug.org/teTeX/, it is available to download from ftp.

The TeXLive distribution allows the installation of the JadeTex macros as an option during installation. They are in the package tex-
htmlxml. The packages tex-extrabin, tex-fontbin, tex-fontsextra, tex-mathextra, tex-psfonts and tex-psutils should also
be installed.

2.9.�Install JadeTeX
JadeTeX is a set of TeX macros that can convert pseudo-TeX files created by openjade to PostScript and PDF formats.

TeXLive comes with JadeTex if it is installed as described above, if the above procedure was not adhered to or a different TeX
distribution was installed and it did not come with the JadeTex macros they can be obtained from
http://sourceforge.net/projects/jadetex/. Follow the installation guide at http://jadetex.sourceforge.net/.
2.10.�Install Ghostscript and GhostView
2.10.1.�Windows

GhostScript and GhostView are used to view and manipulate PostScript files. Download GhostScript from here
http://www.cs.wisc.edu/~ghost/doc/AFPL/get704.htm and GhostView from here
ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/ghostgum/gsv43w32.exe Follow the installation instructions, it does not matter where you
install these files as we do not execute the program from the command line and we do not use its location for anything. If you want you
can setup the PATH so that you can use these tools from the command line but there should be no need to.

2.10.2.�Unix/Linux/BSD

Download GhostScript from: http://sourceforge.net/projects/ghostscript/ and GhostView from:


http://www.cs.wisc.edu/~ghost/doc/AFPL/get704.htm. This resource page provides some more information:
http://www.cs.wisc.edu/~ghost/. Source code and RPM installations are available.

2.11.�Install The Custom Style-Sheets


It is useful to add a customisation layer on top of the DSSSL style-sheets so that it is easy to override options specific to a certain type
of output without having to rewrite the stylesheets themselves

I have produced a custom stylesheet that provides a customisation layer for the DSSSL stylesheets. Download it here: custom.dsl and
save it in the directory /path/to/where/you/installed/the/stylesheets/commom/

For usage instructions see Chapter 4, Using the custom DSSSL style-sheets.

Chapter�3.�Installing And Configuring An XML DocBook System For Windows


Table of Contents

3.1. Introduction
3.2. Installing the JAVA Runtime Environment
3.3. libxml

3.3.1. Windows
3.3.2. Linux/Unix/BSD

3.4. Install Saxon

3.4.1. Setup Catalog Resolver

3.5. FOP

3.5.1. Install Jimi

3.6. DocBook DTD

3.6.1. Catalog Files

3.7. XSL StyleSheets

3.7.1. Custom StyleSheets

3.1.�Introduction
There are a number of different toolchains that can be used to process XML DocBook documents. For XHTML output, Saxon or
xsltproc can be used (there are others like xalan which is not mentioned here). For PDF output there are about three routes, one must
first produce a FO intermediate file from the XML DocBook source, Saxon or xsltproc can be used to do this. The FO output can then
either be rendered to PDF via the xmlpdftex macros or rendered to PDF via FOP. The preferred route is:

(XML DocBook Source) --- (Saxon or xsltproc) ---> (FO) --- (FOP) ---> (PDF)

I personally prefer xsltproc but I tend to adjust my preference depending on the current state of the tools (for instance one might have
support for a particular feature that the other does not), although generally this is not the case. The installation instructions for the less
popular tool chains have been included to afford some redundancy to this file.

Setting up a system for XML Docbook authoring is similar in some respects to the process of setting up a system for SGML DocBook
authoring, some of the steps are identical:

1. Install a TeX distribution

2. Install GhostView

This installation requires a basic understanding of the target operating system, an understanding of how to change the operating
environment etc. This is covered this in documents entitled Configuring A Windows Working Environment and Configuring A Unix
Working Environment.

Note

This installation uses the notation "/path/to/where/you/installed/program" to refer to the location the program was
installed at, forward slashes are always used but for Windows systems these should be replaced with backslashes
and prefixed with "c:".

3.2.�Installing the JAVA Runtime Environment


Saxon and FOP are written in Java, this is primarily because Java has a nice Unicode implementation and XML uses Unicode so it is
slightly easier to program XML processing tools in Java. Java is a byte compiled language, this means that it is compiled to a sort of
Java-machine-language which is then interpreted by the Java runtime environment, this is for portability reasons. At the moment there
are no official machine-level compilers for the Java programming language so there are no executables of the tools written in Java that
can be run natively, hence it is necessary to install the Java runtime environment in order to execute Java programs.

Download the the Java runtime environment from http://java.sun.com/j2se/downloads.html. Follow the installation instructions.

3.3.�libxml
Within this tutorial the primary purpose for installing the libxml C library will be to gain access the tools that come with it. The tools
provide the means to validate and transform XML files. In this tutorial, the program xmllint will be used to validate XML DocBook
files before processing. The program xsltproc can be used to transform XML files. It is a program which uses XSLT.

3.3.1.�Windows

To install libxml on a Windows machine one needs to download the Windows binaries and libraries. These can be obtained from
http://www.zlatkovic.com/pub/libxml/. Download the following:

libxml2-2.6.2+.win32.zip

libxslt-1.1.0.win32.zip

iconv-1.9.1.win32.zip

Note

The three links shown immediately above may be broken since it is common practice to remove old versions from
a download page when they are obsoleted. Goto http://www.zlatkovic.com/pub/libxml/ instead and download the
libxml2..., libxslt..., and iconv... files with the highest version numbers. Some older versions are available
in the directory oldreleases on that server, should one desire them.

It is not necessary to extract the content of these zips entirely, instead the required functionality will be extracted. Create a suitable
directory to contain the stuff that is about to be extracted. For example, on my home machine. If I am running a Windows system I
have a directory called c:\tools which contains all the tools I install. Within c:\tools I have a directory called libxml that contains
the stuff I want from these zips. Create a suitable directory to extract the desired content from the zips into.

Extract the following files from the libxml archive into the directory.

libxml2.dll

xmllint.exe

Extract the following files from the libxslt archive into the directory.

libexslt.dll

libxslt.dll

xsltproc.exe

Extract the following files from the iconv archive into the directory.

iconv.dll

iconv.exe

Append \directory\you\just\unzipped\everything\to to the PATH environment variable.

You might not use all the tools but they are worth having around in case you decide you need them.

3.3.2.�Linux/Unix/BSD

These files are probably already installed on your system, as most modern distributions of these operating systems use XML
processing for some of the more popular components. But you may wish to get the latest versions, in which case, goto
ftp://xmlsoft.org/ and get the latest libxml2 and libxslt. There are gzipped tars and RPMs available, download whichever you prefer. A
list of the latest files at the time of writing is shown below:

libxml2-2.4.25.tar.gz
libxml2-2.4.25-1.i386.rpm
libxml2-2.4.25-1.src.rpm
libxslt-1.0.21.tar.gz
libxslt-1.0.21-1.i386.rpm
libxslt-1.0.21-1.src.rpm

The ftp directory also contains devel versions of the software, this is for people who want to develop with libxml.

3.4.�Install Saxon
1. Download the latest distribution of Saxon from http://saxon.sourceforge.net/ and unzip the zip to a suitable location.

2. Append /directory/you/unzipped/saxon/saxon.jar to the CLASSPATH environment variable. If integration with FOP is


desired, append /directory/you/unzipped/saxon/saxon-fop.jar to the CLASSPATH environment variable. If integration with
JDOM is desired, append /path/to/where/you/unzipped/saxon/saxon-jdom.jar to the CLASSPATH environment variable.

3.4.1.�Setup Catalog Resolver

A catalog resolver provides a way to use catalog files with Java tools like Saxon, the details of this can be found in the documentation
that comes with the installation download.
1. Download the XML Entity and URI Resolvers package from http://wwws.sun.com/software/xml/developers/resolver/. You have
to register to download.

2. Unzip the package to some suitable location, add the file resolver.jar to your CLASSPATH environment variable.

3. Append the directory where the resolver tool was unzipped to the CLASSPATH environment variable.

The Resolver is now ready to use with Saxon but by default it uses the AElfred XML parser that comes with Saxon. This has a few
problems so it is best to invoke Saxon and specify that xerces should be used instead. Note that this requires that xerces be installed,
usually this consists of having the file xerces.jar in the CLASSPATH. It is likely that if other tools such as FOP have been installed that
this is already the case, if it is not, download and install xerces from http://xml.apache.org/xerces-j/.

One invokes Saxon and specifies that xerces should be used as the XML parser like this:

java -
Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
-Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl
-Djavax.xml.transform.TransformerFactory=com.icl.saxon.TransformerFactoryImpl
com.icl.saxon.StyleSheet

This must all be input on one line, this is where Ant (http://jakarta.apache.org/ant/) comes in very useful. The resolver uses a file called
CatalogManager.properties to specify various options, this must be present somewhere on the CLASSPATH. By default this file
resides in the root directory of the resolver zip extraction, hence the adding of this directory to the CLASSPATH in step three of the
installtion above. Details on setting up CatalogManager.properties can be found in the documentation that comes in the downloaded
archive. A simple example is shown below:

#CatalogManager.properties
verbosity=1
# Always use semicolons in this list
catalogs=/lib/docbook-xml-4.2/catalog
# Prefer PUBLIC identifiers over SYSTEM identifiers
prefer=public

This sets up the resolver to use the catalog file specified.

3.5.�FOP
FOP(Formatting Objects Processor) is used to transform FO files to files of other formats. In this tutorial it is used to transform FO
output produced by xsltproc into PDF which is a well known format considered by many to be aesthetically pleasing. The Unix and
Windows installation paths are very similar, the differences will be mentioned where appropriate.

Download the latest version of the Fop application, from http://ftp.plig.org/pub/apache/dist/xml/fop/. Download the zip or tar with bin
as a substring of its name to some suitable location.

On Windows, append /directory/where/you/unzipped/fop/fop.bat to the PATH environment variable.

On Unix, append /directory/where/you/unzipped/fop/fop.sh to the PATH environment variable.

3.5.1.�Install Jimi

Jimi is needed if you want to use PNG images with FOP, download it from http://java.sun.com/products/jimi/# and open the archive.

On Windows, rename JimiProClasses.zip from the archive to jimi-1.0.jar and place it in the
/directory/where/you/unzipped/fop/lib directory.

On Unix, rename JimiProClasses.zip from the archive to JimiProClasses.jarand place it in the


/directory/where/you/unzipped/fop/lib directory.

3.6.�DocBook DTD
The DocBook DTD(Document Type Definition) contains rules which specify the structure of a valid DocBook document, for example,
the order that elements may appear and valid attributes etc. If one has a document which one claims is written in DocBook, it is not
written in DocBook unless it conforms to the DocBook DTD. The DTD is used by tools like xsltproc in transforming DocBook
documents.

DTD's are especially useful when one wants to validate a document to check that it conforms to the DTD one claims it conforms to.
Validation is beneficial because a valid document is less likely to break processing tools (if a valid document does break a processing
tool it is likely that the processing tool is broken and not the document). Hence, the DocBook DTD can be used to validate that a
purported DocBook document really is a DocBook document.

The latest version, at the time of writing, is called DocBook XML 4.2, it is distributed from
http://www.docbook.org/xml/4.2/index.html.

Download the zipped archive, http://www.docbook.org/xml/4.2/docbook-xml-4.2.zip and unzip it to some suitable location. For
example if I was running the Windows operating system I would unzip it to a directory like c:\lib\docbook-xml-4.2, this is the same
as the name of the zip file. If I was running a Unix, Linux, or BSD operating system I would unzip it to a directory like
/lib/docbook/docbook-xml-4.2. You might have noticed on the webpage or in the zip, other files apart from DTD files, these are
auxiliary files and are necessary.

3.6.1.�Catalog Files
When one writes a DocBook document in XML one inserts a DocType declaration at the top of the document to specify that the
document is written in DocBook. This declaration specifies the version of DocBook being used with a PUBLIC ID in the declaration, a
SYSTEM ID in the header specifies where one can find the DTD for DocBook. In the case of DocBook, usually this SYSTEM ID
points to some location on the OASIS(Organization for the Advancement of Structured Information Standards) website because this is
where DocBook's official home is. Some tools used for processing DocBook use the DTD at this location, this is no good when one
wants to process a DocBook document on a computer that does not have Internet access or where accessing the Internet is undesirable.

To overcome the necessity to access the Internet to process DocBook documents one can use a catalog file. A catalog file maps
PUBLIC or SYSTEM IDs to alternate locations. Taking the example from above, one would process the DocBook document that
contained the SYSTEM ID pointing to the Internet with a tool and specify a catalog file to use. The catalog file would map the
SYSTEM ID pointing to the Internet to a copy of the DTD on the local system, thus circumventing the need for any Internet access.

The DocBook zip that was just downloaded does actually contain it's own catalog file (catalog.xml. This does not seem to provide the
desired functionality without modification. Instead of modifying that catalog file, create a new one called catalog in the docbook-
xml-4.2 directory. Put the following content into it:

<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<group xml:base="." prefer="public" >
<public publicId="-//OASIS//DTD DocBook XML V4.2//EN" uri="file:///c:/lib/docbook-xml-
4.2/docbookx.dtd"/>
</group>
</catalog>

This maps the PUBLIC ID for DocBook XML V4.2 to a local copy of it's DTD. The example above was taken from a Windows
system, modify the value of the uri attribute to point to the location of the DTD on your system. On a Unix system this could be
file:///lib/docbook/docbook-xml-4.2/docbookx.dtd.

The processing tools must know where this catalog file is in order to use the functionality it provides. This is achieved via an
environment variable called XML_CATALOG_FILES, create this environment variable and make it point to the catalog file you just
created. You could add similar entries to the catalog file shown above to map other DTDs you desire to use to local copies of their
DTD's.

3.7.�XSL StyleSheets
XSL stylesheets dictate how a document written in XML should be transformed using XSLT to a particular output format. In the case
of DocBook, Norman Walsh has already written, and regularly maintains some stylesheets for DocBook that provide rules for
transformations from an XML DocBook document to the most commonly desirable output formats such as XHTML and PDF. The
installation for Unix and Windows machines is the same.

Download the latest stylesheets from http://sourceforge.net/project/showfiles.php?group_id=21935 and unzip the zip or gzipped tar to
some suitable location. If I was running a Windows system I would use c:\lib\docbook-xsl\, if I was using a Unix system I would
use c:\lib\docbook\docbook-xsl. The stylesheets are now ready to use.

3.7.1.�Custom StyleSheets

The output produced by the stylesheets mentioned above is reasonable but the stylesheets mentioned above are a standard distribution
and as a consequence seem to be designed to cater for the needs of the many, which is sensible, unfortunately. One may modify the
stylesheets directly but more often one creates a customisation layer which imports the standard stylesheets and then one overrides
specific aspects of the standard stylesheets or adds extra functionality within the customisation layer according to ones tastes. I have
created a customisation layer which looks good enough for standard applications and am offering it to download.

This is particularly pertinent if you study at The University Of Birmingham because any documentation created by me there in
DocBook uses this customisation layer, all the tutorials I have written conform to these stylesheets. If you your documents to have the
same style as the tutorials then use this customisation layer. It is probably worth downloading the customisation layer anyway so you
can see how one goes about creating a customisation layer. Here is the zipped customisation layer: custom-stylesheets.zip.

Unzip the zip to where you want the customisation layer to be situated, this could be within the stylesheets directory or in separate
directory. If you unzip it to the stylesheets directory the customisation layer will unzip into the directories common, fo and xhtml. If you
unzip to a separate directory these directories will be created.

Wherever you unzip the zip, it is important to change the references of the imports in the files so that they reflect the state of your
system, the files fo/customfo.xsl, xhtml/customxhtml.xsl and xhtml/customchunk.xsl all have references that may need to be
modified. For example, the file fo/customfo.xsl has the import line:

<!-- Import standard fo style-sheet -->


<xsl:import href="file:///c:/lib/docbook-xsl/fo/docbook.xsl"/>

Change this to point to /where/you/put/the/stylesheets/fo/docbook.xsl

Similarly, change the entry in customchunk.xsl to point to /where/you/put/the/stylesheets/xhtml/chunk.xsl and the entry in
customxhtml.xsl to point to /where/you/put/the/stylesheets/xhtml/docbook.xsl. The advantage of unzipping the zip in the
same location as the standard stylesheets is that the import links may be relative (the import links can always be relative assuming the
stylesheets are on the same machine, but for clarity if I am using a different directory for the customisation stylesheets I will make the
import references absolute).

I have only provided customisations for FO and XHTML. It will become apparent how to use the customisation layer in the section on
using the tools later. The provided customisations are listed below:

fo/customfo.xsl - Use this to generate custom FO

xhtml/customxhtml.xsl - Use this to generate custom XHTML (segmented)

xhtml/customxchunk.xsl - Use this to generate custom XHTML (chunked)

More information about customising stylesheets can be found at http://www.sagehill.net/xml/docbookxsl/.

Chapter�4.�Using The SGML Tools


Table of Contents

4.1. About this chapter


4.2. Validating an SGML DocBook Document with onsgmls
4.3. Using OpenJade to convert SGML DocBook source to an intermediate TeX format
4.4. Using OpenJade to convert SGML DocBook source to (single file)HTML
4.5. Using OpenJade to convert SGML DocBook source to (Chunked) HTML
4.6. Using openjade to convert SGML DocBook source to RTF
4.7. Using jadetex to convert (openjade created) TeX to DVI
4.8. Using JadeTeX to convert (openjade created)TeX to PDF
4.9. Using dvipsto convert DVI to PS
4.10. Using osx to convert SGML DocBook source to an XML tree
4.11. Using the custom DSSSL stylesheets

4.1.�About this chapter


This chapter provides concrete examples of how to use the tools associated with the processing of SGML DocBook source files.

Conventions used throughout this chapter:

in.sgml is used to represent the input SGML DocBook source file.

out.xxx is used to represent the output of some operation, where xxx is some extension.

In most of the examples, command sequences are used that are non operating system specific. The notation /path/to/.../
maybe used as a prefix to the location of certain files, the real directory location should substitute the generic terms and the file
separators should be replaced with those used on the target operating system.

Note

When one uses the tools to produce PDF output, if callout or admonition graphics were used, one should first copy
the images directory into the build directory. If one does not do this, the PDF tools will not be able to find the
images and hence problems will occur. The production of HTML output formats does not require this as the
images are not actually required to build the output but are referenced from outputted HTML pages, hence the
referencing of images is controlled via the output tools and embedded into the HTML page. The location of the
callout and admonitions graphics can be set in the stylesheets or via command line parameters.

4.2.�Validating an SGML DocBook Document with onsgmls


It is useful to validate an SGML DocBook document against the DocBook DTD before attempting to process the SGML DocBook
source because if the document conforms to the DTD there should be no errors during processing. If there are errors during processing
and the document is valid, one can infer that the problem is very unlikely to lie with the document but somewhere else such as the
processing tool. onsgmls is used to validate SGML DocBook documents.

onsgmls -s in.sgml

If no errors occur, onsgmls will exit silently (indicative of the -s option). If there are errors messages will be output describing where
in the input file each error occurred and a short description of the error. An example onsgmls error message is shown below:

onsgmls:sgmlsys-chapter3.sgml:73:9:E: end tag for "PROGRAMLISTING" omitted, but its


declaration does not permit this.

onsgmls error messages take the following form:

program-name : input-file : line-number : column-number : error-type : error-description

4.3.�Using OpenJade to convert SGML DocBook source to an intermediate TeX


format

openjade -t tex -d /path/to/stylesheets/print/docbook.dsl in.sgml

This will create the file in.tex. The stylesheet to be used for the operation is specified using the -d option. In this case, Norman
Walsh's stylesheet for print output was chosen. The output type was specified using the -t option. It is possible to redirect the output to
a file of your choice (by defaultopenjade will use the same name as in.sgml and create in.tex. Redirection is performed in the usual
manner that redirection is performed on the target operating system.

4.4.�Using OpenJade to convert SGML DocBook source to (single file)HTML

openjade -t> sgml -V nochunks -d /path/to/dsssl/html/docbook.dsl in.sgml > out.html

Notice that the output from the openjade was redirected to a desired output file, if this is not done openjade outputs to the standard
output stream.

4.5.�Using OpenJade to convert SGML DocBook source to (Chunked) HTML

openjade -t sgml -d /path/to/stylesheets/html/docbook.dsl in.sgml

This produces the output file t1.html, as well as a number of other auxiliary files. The type of the output is specified as SGML
because HTML is defined in SGML. Norman Walsh's HTML output stylesheet was used.y. The HTML produced is segmented, a new
HTML page is generated for each each section and an index.html file is generated as the entry point into the document.

4.6.�Using openjade to convert SGML DocBook source to RTF

openjade -t -d /path/to/stylesheets/print/docbook.dsl in.sgml

4.7.�Using jadetex to convert (openjade created) TeX to DVI


The TeX files produced by openjade cannot be processed using the standard TeX processing tools, the JadeTeX macro pack must be
used.

Unix/Linux/BSD users should probably use the following command sequence:

jadetex in.tex

This should work fine. Sometimes one can get errors associated with memory usage when using this command, a recent installation of
jadetex should not have this problem. If the jadetex command does not exist try:

hugelatex "&jadetex" in.tex

Windows users should use the following command sequence:

jadetex in.tex

Unix users may encounter memory usage errors when using the above commands, some TeX distributions come with the command
hugelatex which uses larger memory parameters. If hugelatex is not installed or the memory parameters are too small, TeX may
generate an error like this:

! TeX capacity exceeded, sorry [pool size=21903].

To fix this, one can alter the memory pool size in the file texmf.cnf (situated in the web2c directory of the TeX installation). Here is a
texmf.cnf file from a working installation of TeX and jadetex:

main_memory.latex = 1500000
param_size.latex = 1500
stack_size.latex = 1500
hash_extra.latex = 15000
string_vacancies.latex = 45000
pool_free.latex = 47500
nest_size.latex = 500
save_size.latex = 5000
pool_size.latex = 1250000
max_strings.latex = 55000
font_mem_size.latex= 400000
main_memory.jadetex = 1500000
param_size.jadetex = 1500
stack_size.jadetex = 1500
hash_extra.jadetex = 15000
string_vacancies.jadetex = 45000
pool_free.jadetex = 47500
nest_size.jadetex = 500
save_size.jadetex = 5000
pool_size.jadetex = 1250000
max_strings.jadetex = 55000
font_mem_size.jadetex= 400000

main_memory.pdfjadetex = 2500000
param_size.pdfjadetex = 1500
stack_size.pdfjadetex = 1500
hash_extra.pdfjadetex = 50000
string_vacancies.pdfjadetex = 55000
pool_free.pdfjadetex = 47500
nest_size.pdfjadetex = 500
save_size.pdfjadetex = 5000
pool_size.pdfjadetex = 1250000
max_strings.pdfjadetex = 55000

This is how the file came upon installation, the memory allocated is relatively huge, indicating that any modern TeX installation should
not have any memory problems. Increase the values in the above file that are indicated as being too small by the error messages
produced if necessary.

The command sequence will produce in.dvi, hello.aux and hello.log. It is recommended that this command sequence be executed
at least 3 times, this is so that the in.aux is correctly updated with page numbers.

4.8.�Using JadeTeX to convert (openjade created)TeX to PDF


Unix users should try using the following command sequence:

pdfjadetex in.tex

If the above command did not exist, try:

%hugelatex "&pdfjadetex" in.tex

Windows users should use the following command sequence:

pdfjadetex in.tex
It is recommended that this command sequence be executed at least 3 times, this is so that the in.aux is correctly updated with page
numbers. This produces the files in.aux and in.pdf.

If memory usage error messages were output see the secion on memory problems. Alternatively one can use the command ps2pdf
which comes with GhostScript to convert files from PostScript to PDF:

ps2pdf in.ps

4.9.�Using dvipsto convert DVI to PS

dvips in.dvi -o out.ps

This will produce the PostScript file out.ps.

4.10.�Using osx to convert SGML DocBook source to an XML tree

osx in.sgml > out.xml

This will produce the output file in.xml, redirection can be used to redirect the output to a specific file.

There is the possibility that the conversion could generate errors because XML does not allow the use of certain SGML idiosyncrasies.
This may be due to use of characters that XML does not allow unless referenced via their Unicode number.

In XML you would have to use a data entity instead, where a character is referenced numerically (&#123;) or hexadecimally
(&#x12AB). See http://www.w3.org/TR/xml-infoset/#infoitem.character

4.11.�Using the custom DSSSL stylesheets


To use the custom stylesheets one specifies the custom stylesheet as the stylesheet that openjade should use. More than one output
format is included in the single custom stylesheet provided in the installation section, the -i option is used to determine which of the
output fromats should be used. The generation of HTML output is shown below:

openjade -i output.html -t sgml -d /path/to/stylesheets/common/custom.dsl in.sgml

HTML output was specified using the -i option with the value output.html. The custom stylesheet was specified using the -d. The
generation of intermediate TeX format is shown below:

openjade -i output.print -t tex -d /path/to/docbookdsssl/common/custom.dsl in.sgml

HTML was specified using the -i with the output.print value. The custom stylesheet was specified using the -d. RTF can be produced
by specifying the RTF backend with the -t option.

It is worth taking a look at the custom stylesheets to see how a customisation layer can be created.

Chapter�5.�Using the XML Tools


Table of Contents

5.1. About this chapter


5.2. Using xmllint to validate an XML DocBook document
5.3. Using xsltproc to generate (Single file)XHTML output from an XML Docbook document
5.4. Using xsltproc to generate XHTML(Segmented) output from an XML Docbook document
5.5. Using xsltproc to generate FO output from an XML Docbook document
5.6. Using xsltproc to generate HTMLhelp output from XML Docbook source
5.7. Using xsltproc to generate Javahelp output from XML Docbook source
5.8. Using Saxon to generate (Single file) HTML output from XML DocBook source
5.9. Using Saxon to generate (Single file) XHTML output from XML DocBook source
5.10. Using Saxon to generate FO output from XML Docbook source
5.11. Using FOP to generate PDF output from XSL FO input
5.12. Using pdfxmltex to generate PDF output from XSL FO input
5.13. General Usage

5.1.�About this chapter


This chapter provides concrete examples of how to use the tools associated with the processing of SGML DocBook source files.

Conventions used throughout this chapter:

in.sgml is used to represent the input SGML DocBook source file.

out.xxx is used to represent the output of some operation, where xxx is some extension.

In most of the examples, command sequences are used that are non operating system specific. The notation /path/to/.../
maybe used as a prefix to the location of certain files, the real directory location should substitute the generic terms and the file
separators should be replaced with those used on the target operating system.

Note

When one uses the tools to produce PDF output, if callout or admonition graphics were used, one should first copy
the images directory into the build directory. If one does not do this, the PDF tools will not be able to find the
images and hence problems will occur. The production of HTML output formats does not require this as the
images are not actually required to build the output but are referenced from outputted HTML pages, hence the
referencing of images is controlled via the output tools and embedded into the HTML page. The location of the
callout and admonitions graphics can be set in the stylesheets or via command line parameters.

5.2.�Using xmllint to validate an XML DocBook document


In order to check the syntactic accordance of a DocBook document with the DocBook DTD one may use xmllint.

xmllint --valid --noout in.xml

The --valid option specifies that xmllint should validate the document against the DTD and the --noout option specifies that no
output should be produced if there are no errors, hence if the document being validated is valid, xmllint will exit silently. If the
document is invalid xmllint will output an error similar to this:

docbook.xml:1: error: Start tag expected, '< not found


?xml version="1.0" encoding='ISO-8859-15'?>
^

Which specifies that there is a missing start tag on line one.

Note

The --loaddtd option can be used to specify an external DTD to validate the input document with.
5.3.�Using xsltproc to generate (Single file)XHTML output from an XML Docbook
document

xsltproc file:///path/to/docbook-xsl/xhtml/docbook.xsl in.xml > out.html

This will produce a single XHTML file according to the XSL stylesheet specifications.

5.4.�Using xsltproc to generate XHTML(Segmented) output from an XML


Docbook document

xsltproc file:///path/to/docbook-xsl/xhtml/chunk.xsl in.xml

This will produce a set of XHTML files of the document where each section is on a separate HTML page. The layout will accord to the
XSL stylesheet specified. The separate files will be given unique names that correspond to the different sections of the book, e.g
index.html, ar01s02.html and ar01s03.html.

5.5.�Using xsltproc to generate FO output from an XML Docbook document

xsltproc file:///path/to/docbook-xsl/fo/docbook.xsl in.xml > out.fo

This will produce output as an XSL FO(Formatting object), this is an intermediate file type that can be used by other programs to
generate other types of output, such as PDF.

5.6.�Using xsltproc to generate HTMLhelp output from XML Docbook source

xsltproc file:///path/to/docbook-xsl/htmlhelp/htmlhelp.xsl in.xml

This will produce a set of HTML files of the document where each section is on a separate HTML page. This will also generate
htmlhelp.hhp and toc.hhc.

5.7.�Using xsltproc to generate Javahelp output from XML Docbook source

xsltproc file:///path/to/docbook-xsl/javahelp/javahelp.xsl in.xml

This will produce a set of HTML files of the document where each section is on a separate HTML page. This will also generate the
JavaHelp helpset file jhelpset.hs, the JavaHelp table of contents file jhelptoc.xml, the JavaHelp map file jhelpmap.jhm and the
JavaHelp index file jhelpidx.xml.

5.8.�Using Saxon to generate (Single file) HTML output from XML DocBook
source

java com.icl.saxon.StyleSheet -o out.html in.xml file:///path/to/docbook-xsl/html/docbook.xsl

This will produce a single HTML file output according to XSL stylesheet specified.

5.9.�Using Saxon to generate (Single file) XHTML output from XML DocBook
source

java com.icl.saxon.StyleSheet -o out.html in.xml file:///path/to/docbook-xsl/xhtml/docbook.xsl

This will produce a single XHTML file output according to XSL stylesheet specified.

5.10.�Using Saxon to generate FO output from XML Docbook source

java com.icl.saxon.StyleSheet -o in.xml file:///path/to/docbook-xsl/fo/docbook.xsl

This will produce output as an XSL FO(Formatting object), this is an intermediate file type that can be used by other programs to
generate other types of output, such as PDF.

5.11.�Using FOP to generate PDF output from XSL FO input


In order to execute this conversion you will need to have generated XSL FO output by using xsltproc or some other tool capable of
doing so.

fop.bat in.fo out.pdf

Substituting fop.sh for fop.bat on Unix derivatives. This will generate a PDF file named according to the name provided as the
second argument. FOP will probably generate lots of warnings about un-implemented features whilst generating this output, this is
normal and can be ignored.

5.12.�Using pdfxmltex to generate PDF output from XSL FO input

pdfxmltex in.fo

It is recommended that this command sequence be executed at least 3 times that in.aux is correctly updated with page numbers. This
will produce the files in.aux and in.pdf.

5.13.�General Usage
Assume that a file called test.xml has been created in XML DocBook. Assume that the stylesheets are located in a directory called
/lib/docbook-xsl/ One would create XHTML output like this:

xsltproc file:///lib/docbook-xsl/xhtml/docbook.xsl test.xml > test.html

One would create PDF output in two steps, first create the FO output using xsltproc:

xsltproc file:///lib/docbook-xsl/fo/docbook.xsl test.xml > test.fo

Next, process the FO output with FOP to produce the PDF file:

fop.bat in.fo out.pdf

If you want to use the custom stylesheets you simply modify the stylesheet parameter so that it points to the custom stylesheet you
want to use. Assuming an install of the customisation layer mentioned above in the same location as the standard stylesheets one could
generate XHTML output that conformed to the custom stylesheet for XHTML like this:

xsltproc file:///lib/docbook-xsl/xhtml/customxhtml.xsl test.xml > test.html

Similarly, FO output could be produced.

Chapter�6.�Using The SGML Tools To Process XML DocBook Documents


Table of Contents

6.1. About This Chapter


6.2. Using onsgsmls to validate XML DocBook documents
6.3. Using openjade to convert XML DocBook to (segmented) HTML
6.4. Using openjade to convert XML DocBook to (single file) HTML
6.5. Using openjade to convert from XML DocBook to intermediate TeX format
6.6. Using openjade to convert from XML DocBook to RTF
6.7. Using jadetex to convert from (openjade created) intermediate TeX format to DVI
6.8. Using JadeTeX to convert (openjade created)TeX to PDF
6.9. Using dvips to convert from DVI to PS

6.1.�About This Chapter


It is possible to use the SGML tools to process XML DocBook documents, this can be useful if the XML tools are currently broken or
it is preferable to use the SGML tools, for example, onsgmls is considered to produce more meaningful error messages than xmllint.
The rest of this chapter provides some concrete examples.

Conventions used throughout this chapter:

in.sgml is used to represent the input SGML DocBook source file.

out.xxx is used to represent the output of some operation, where xxx is some extension.

In most of the examples, command sequences are used that are non operating system specific. The notation /path/to/.../
maybe used as a prefix to the location of certain files, the real directory location should substitute the generic terms and the file
separators should be replaced with those used on the target operating system.

When one uses the tools to produce PDF output, if callout or admonition graphics were used, one should first copy the images
directory into the build directory. If one does not do this, the PDF tools will not be able to find the images and hence problems will
occur. The production of HTML output formats does not require this as the images are not actually required to build the output but are
referenced from outputted HTML pages, hence the referencing of images is controlled via the output tools and embedded into the
HTML page. The location of the callout and admonitions graphics can be set in the stylesheets or via command line parameters.

Note

When one uses SGML tools to process XML documents there may be slight differences in the way that filenames
are specified, for example, xmllint, and xsltproc implements a true URI scheme, more about which can be found
at http://www.ietf.org/rfc/rfc2396.txt, an example of a URI is shown below:.

file:///path/to/wherever/

Most of the SGML tools do not employ this scheme and it is only necessary to specify the filename like this:

/path/to/wherever/

To process XML files the SGML tools reference a file called xml.dcl which is the XML declaration, this is
bundled with the OpenJade suite in the pubtext directory, it may be a good idea to put this somewhere more
convenient.

6.2.�Using onsgsmls to validate XML DocBook documents

onsgmls -s /path/to/openjade-1.3.1/pubtext/xml.dcl test.xml

If the document is valid the program will exit silently, otherwise errors will be produced. See error descriptions

6.3.�Using openjade to convert XML DocBook to (segmented) HTML

openjade -t xml -d /path/to/dssslstylesheets/html/docbook.dsl


/path/to/openjadedir/pubtext/xml.dcl in.xml

The fact an XML file was being processed was specified using the -t option and Norman Walsh's DSSSL HTML stylesheet was
specified using the -d. After this, the XML declaration was passed to openjade so that openjade knew how to deal with the XML
document it was about to receive which was passed in as the last parameter. This produces the HTML output in chunked format.

6.4.�Using openjade to convert XML DocBook to (single file) HTML

openjade -V nochunks -t xml -d /path/to/dssslstylesheets/html/docbook.dsl


/path/to/openjadedir/pubtext/xml.dcl in.xml

Single file HTML output was selected using the -V nochunks option. The fact an XML file was being processed was specified using
the -t option and Norman Walsh's DSSSL HTML stylesheet was specified using the -d. After this, the XML declaration was passed to
openjade so that openjade knew how to deal with the XML document it was about to receive which was passed in as the last
parameter. This produces the HTML output in single file format.

6.5.�Using openjade to convert from XML DocBook to intermediate TeX format

openjade -t tex -d /path/to/dssslstylesheets/print/docbook.dsl


/path/to/openjadedir/pubtext/xml.dcl in.xml

The TeX input file type was specified using the -t option. Norman Walsh's DSSSL print stylesheet was specified using the -d option.
After this, the XML declaration was passed to openjade so that openjade knew how to deal with the XML document it was about to
receive which was passed in as the parameter after. The output .tex will have to be processed with special TeX macros in order to
produce other output formats.

6.6.�Using openjade to convert from XML DocBook to RTF

openjade -t rtf -d /path/to/dssslstylesheets/print/docbook.dsl


/path/to/openjadedir/pubtext/xml.dcl in.xml

The RTF input type was specified using the -t option and Norman Walsh's DSSSL print stylesheet was specified using the -d option.
After this, the XML declaration was passed to openjade so that openjade knew how to deal with the XML document it was about to
receive which was passed in as the parameter after.

6.7.�Using jadetex to convert from (openjade created) intermediate TeX format to


DVI
The TeX files produced by openjade cannot be processed using the standard TeX commands, instead, the JadeTeX macro pack is
used.

Unix users should try using the following command sequence:

jadetex in.tex

If the above command did not exist, try:

hugelatex "&jadetex" in.tex

Windows users should use the following command sequence:

jadetex in.tex

It is recommended that this command sequence be executed at least 3 times, this is so that the in.aux is correctly updated with page
numbers. This produces the files in.dvi, hello.aux and hello.log.

If memory usage error messages were output see the secion on memory problems.

6.8.�Using JadeTeX to convert (openjade created)TeX to PDF


Unix users should try using the following command sequence:

pdfjadetex in.tex

If the above command did not exist, try:

%hugelatex "&pdfjadetex" in.tex

Windows users should use the following command sequence:

pdfjadetex in.tex

It is recommended that this command sequence be executed at least 3 times, this is so that the in.aux is correctly updated with page
numbers. This produces the files in.aux and in.pdf.

If memory usage error messages were output see the secion on memory problems. Alternatively one can use the command ps2pdf
which comes with GhostScript to convert files from PostScript to PDF:

ps2pdf in.ps

6.9.�Using dvips to convert from DVI to PS

dvips in.dvi -o out.ps

This produces the PostScript file out.ps.


Introduction To Authoring DocBook Documents
Table of Contents

7. Creating An SGML DocBook Document

7.1. Declaring the document type


7.2. The use of PUBLIC identifiers in SGML
7.3. The use of SYSTEM identifiers in SGML
7.4. An SGML DocBook article template
7.5. An SGML DocBook book template

8. Creating an XML DocBook document

8.1. Declaring The Document Type


8.2. The use of PUBLIC and SYSTEM identifiers in XML
8.3. Creating an XML DocBook document

8.3.1. An article template


8.3.2. An example XML DocBook Book

9. DocBook Document Examples

9.1. Common DocBook Elements

9.1.1. <para>
9.1.2. <programlisting>
9.1.3. Entities for special characters
9.1.4. <screen>
9.1.5. <ulink>
9.1.6. Lists

9.1.6.1. <itemizedlist>
9.1.6.2. <orderedlist>

9.1.7. Some common inline elements

9.2. Including Images


9.3. Tables

10. Auxiliary Tools for DocBook Authoring

10.1. Editors

10.1.1. VI/VIM/GVIM
10.1.2. Emacs
10.1.3. ThotBook
10.1.4. EpcEdit
10.1.5. Xeena
10.1.6. The rest

10.2. Spell Checking

10.2.1. Aspell

11. References

11.1. Internet Resources Used

Chapter�7.�Creating An SGML DocBook Document


Table of Contents

7.1. Declaring the document type


7.2. The use of PUBLIC identifiers in SGML
7.3. The use of SYSTEM identifiers in SGML
7.4. An SGML DocBook article template
7.5. An SGML DocBook book template

7.1.�Declaring the document type


When marking up documents in a DTD it is standard practice to include a DOCTYPE declaration so that the processing tools 'know'
what DTD the document being processed conforms to. A typical DOCTYPE declaration for a document marked up in DocBook
SGML can be seen below:

<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook V4.1//EN">

Notice that the markup is enclosed within:

<! ... >

These are SGML directives so are enclosed within the special tags <! and >. The distinguishing feature is that an exclamation mark
follows the '<' which opens the directive section. The SGML directives define various aspects of the SGML document itself. The
DOCTYPE declaration as a whole is known as the prologue.

Immediately following the opening of the prologue is the keyword DOCTYPE then a word such as chapter or book, this specifies the
root element of the document and is exactly the name of the tag that will be used to open and close the markup after the prologue.
Example:

<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook V4.1//EN">


<chapter><title>The Theory Of Special Relativity</title>
<para>
The principle of the physical relativity of all uniform motion...
</para>
</chapter>

Notice that the start and end tags of the document are defined by the root element specified in the DOCTYPE declaration in the
prologue of the document.

What follows is the keyword PUBLIC this specifies that what follows that is a public identifier, which is described in more detail in the
next section, but essentially defines what type of document this is.

7.2.�The use of PUBLIC identifiers in SGML


A public identifier is an indirect way of specifying what DTD a document was created under. (The markup language that was used to
write the document). A particular document type is associated with a particular DTD which specifies the particular details of how this
type of document should be structured. Hence processing tools can know how to parse and validate your document by examining this
DTD.

The processing tools can use the public identifier, along with catalog file which maps the public identifier to a DTD. An example from
a catalog file called docbook.cat is shown below:

-- DocBook driver file .................................................. --


PUBLIC "-//OASIS//DTD DocBook V4.1//EN" "docbook.dtd"
The whole of the OpenJade catalog file found in the dsssl subdirectory can be seen below:

PUBLIC "-//James Clark//DTD DSSSL Flow Object Tree//EN" "fot.dtd"


PUBLIC "ISO/IEC 10179:1996//DTD DSSSL Architecture//EN" "dsssl.dtd"
PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" "style-sheet.dtd"
PUBLIC "-//OpenJade//DTD DSSSL Style Sheet//EN" "style-sheet.dtd"
SYSTEM "builtins.dsl" "builtins.dsl"

Notice that each public identifier is mapped to a SYSTEM identifier which specifies the location of the actual DTD for the DOCTYPE,
in these cases, they happen to be in the same directory as the catalog file but they do not have to. The locations of the files here are not
defined by formal URIs because it is not necessary.

A PUBLIC identifier is essentially of the format

prefix//owner-identifier//text-class text-description//language//display version

For more information see Public Identifiers, System Identifiers, and Catalog Files http://www.docbook.org/tdg/en/html/ch02.html#s-
pid-sid-catalogs.

7.3.�The use of SYSTEM identifiers in SGML


A SYSTEM identifier specifies the exact location of the DTD that the document conforms to. SYSTEM identifiers may follow
PUBLIC identifiers as in the example below:

<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" "docbook.dtd">

Or they may occur on their own:

<!DOCTYPE book SYSTEM "customdocbook.dtd">

The above example specifies that the document conforms to the DTD defined in the file "customdocbook.dtd". More information about
SGML declarations can be found here: http://www.oasis-open.org/cover/wlw11.html.

7.4.�An SGML DocBook article template

<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN">


<article>
<articleinfo>
<title>Your title here</title>
<author>
<firstname>Your first name</firstname>
<surname>Your surname</surname>
<affiliation>
<address><email>Your e-mail address</email></address>
</affiliation>
</author>
<copyright>
<year>1998</year>
<holder role="mailto:your e-mail address">Your name</holder>
</copyright>
<pubdate role="rcs">$Date: 2003/01/08 10:27:39 $</pubdate>
<releaseinfo>$Id: DocBookSys-Chapter7-SGML-Creating.xml,v 1.1.1.1 2003/01/08 10:27:39 ug55axm
Exp $</releaseinfo>
<abstract>
<para>Include an abstract of the article&apos;s contents here.</para>
</abstract>
</articleinfo>
<sect1><title>Section 1</title>
<para>
My first article!
</para>
</sect1>
<sect2><title>Section 2</title>
<para>
Brilliant!
</para>
</sect2>
</article>

This is an article template and illustrates some of the features of docbook. The file can be validated using onsgmls like this:

onsgmls -s articletemplate.sgml

This should produce no errors and exit silently because the document is structured correctly. Chunked HTML output can be generated
from this file like this:

openjade -t sgml -d /path/to/docbook/dbdsssl/html/docbook.dsl articletemplate.sgml

7.5.�An SGML DocBook book template


DocBook books are generally for projects over 25 pages long, they allow the inclusion of chapters and parts, a template for a book is
shown below:

<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook V4.1//EN'>


<book>
<bookinfo>
<title>Your title here</title>
<author>
<firstname>Your first name</firstname>
<surname>Your surname</surname>
<affiliation>
<address><email>Your e-mail address</email></address>
</affiliation>
</author>
<copyright>
<year>1998</year>
<holder role='mailto:your e-mail address'>Your name</holder>
</copyright>
<pubdate role='rcs'>$Date: 2003/01/08 10:27:39 $</pubdate>
<releaseinfo>$Id: DocBookSys-Chapter7-SGML-Creating.xml,v 1.1.1.1 2003/01/08 10:27:39 ug55axm
Exp $</releaseinfo>
<abstract>
<para>Include an abstract of the book&apos;s contents here.</para>
</abstract>
</bookinfo>
<part><title>Part1</title>
<chapter><title>Part 1, Chapter 1</title>
<sect1><title>Part1, Chapter 1, Section1</title>
<para>
Hello there!
<para>
</sect1>
</chapter>
<chapter><title>Part 1, Chapter 2</title>
<sect1><title>Part1, Chapter 2, Section 1</title>
<para>
Hi there!
<para>
</sect1>
</chapter>
</part>
<part><title>Part2</title>
<chapter><title>Part 2, Chapter 1</title>
<sect1><title>Part 2, Chapter 1, Section1</title>
<para>
GoodDay there!
<para>
</sect1>
<sect1><title>Part2, Chapter1, Section2</title>
<para>
GoodNight there!
<para>
</sect1>
</chapter>
</part>
</book>

This file can be validated using onsgmls like this:

onsgmls -s booktemplate.sgml

This should produce no errors and exit silently because the document is structured correctly. RTF output can be generated like this:

openjade -t rtf -d /path/to/docbook/dbdsssl/print/docbook.dsl booktemplate.sgml

There is a DocBook element quick reference card available from http://www.dpawson.co.uk/docbook/reference.html#d3e60.

Chapter�8.�Creating an XML DocBook document


Table of Contents

8.1. Declaring The Document Type


8.2. The use of PUBLIC and SYSTEM identifiers in XML
8.3. Creating an XML DocBook document

8.3.1. An article template


8.3.2. An example XML DocBook Book

8.1.�Declaring The Document Type


XML documents must declare that they are XML documents like this:

<?xml version="1.0" encoding="UTF-8"?>

When marking up documents in a DTD it is standard practice to include a DOCTYPE declaration so that the processing tools 'know'
what DTD the document being processed conforms to. A typical DOCTYPE declaration for a document marked up in DocBook XML
can be seen below:

<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"


"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

Notice that the markup is enclosed within:

<! ... >

These are XML directives so are enclosed within the special tags <! and >. The distinguishing feature is that an exclamation mark
follows the '<' symbol which opens the directive section. The XML directives define various aspects of the XML document.

Immediately following the opening of the prologue is the keyword DOCTYPE then a word such as chapter or book, this specifies the
root element of the document and is exactly the name of the tag that will be used to open and close the markup of the document which
appears after the prologue. An example is shown below:

<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"


"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<chapter><title>The Theory Of Special Relativity</title>
<para>
The principle of the physical relativity of all uniform motion...
</para>
</chapter>

Notice that the start and end tags of the document are defined by the root element specified in the DOCTYPE declaration in the
prologue of the document.

What follows is the keyword PUBLIC, this specifies that what follows that is a public identifier, which defines what type of document
the document is.

8.2.�The use of PUBLIC and SYSTEM identifiers in XML


A public identifier is an indirect way of specifying what DTD a document was created under. (The markup language that was used to
write the document). A particular document type is associated with a particular DTD which specifies the particular details of how this
type of document should be structured. Hence processing tools can know how to parse and validate your document by examining this
DTD.

The processing tools can use the public identifier, along with catalog file which maps the public identifier to a DTD. An example
catalog file is shown below:

<catalog xmlns='urn:oasis:names:tc:entity:xmlns:xml:catalog'>
<group xml:base='/usr/share/xml/' prefer='public' >
<public
publicId='-//OASIS//DTD DocBook XML V4.2//EN'
uri='file:///path/to/docbook/docbook-V4.2/docbookx.dtd'/>
</group>
</catalog>

This catalog file maps the PUBLIC ID ";-//OASIS//DTD DocBook XML V4.2//EN", which might be present in the prologue of a
DocBook document, to the file "file:///path/to/docbook/docbook-V4.2/docbookx.dtd".

XML requires that if one uses a PUBLIC ID one also provides a SYSTEM ID. Usually the official URL of the DTD on the Internet is
used as the SYSTEM identifier in the actual document, following the PUBLIC identifier. If the processing tools fail to find a mapping
from the PUBLIC identifier to a SYSTEM identifier in the catalog file(s) they will fall back to using the SYSTEM identifier specified
in the document.

A PUBLIC identifier is essentially of the format

prefix//owner-identifier//text-class text-description//language//display version

For more information see Public Identifiers, System Identifiers, and Catalog Files http://www.docbook.org/tdg/en/html/ch02.html#s-
pid-sid-catalogs.

A SYSTEM identifier specifies the exact location of the DTD that the document conforms to. SYSTEM identifiers may follow
PUBLIC identifiers as in the example below:

<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" "docbook.dtd">


Or they may occur on their own:

<!DOCTYPE book SYSTEM "customdocbook.dtd">

The above example specifies that the document conforms to the DTD defined in the file "customdocbook.dtd".

8.3.�Creating an XML DocBook document


For the ultimate reference guide see DocBook: The Definitive Guide. A template for a DocBook article is shown below:

Note

The output illustrated in this section was produced using a customisation of the stylesheets hence output on
systems not implementing the same customisations may differ.

8.3.1.�An article template

<?xml version="1.0" encoding='UTF-8'?>


<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<article>
<articleinfo>
<title>Your title here</title>
<author>
<firstname>Your first name</firstname>
<surname>Your surname</surname>
<affiliation>
<address><email>Your e-mail address</email></address>
</affiliation>
</author>
<copyright>
<year>2002</year>
<holder role="mailto:your e-mail address">Your name</holder>
</copyright>
<abstract>
<para>Include an abstract of the article's contents here.</para>
</abstract>
</articleinfo>
<sect1><title>Section 1</title>
<para>
blah blah blah
</para>
</sect1>
<sect1><title>Section 2</title>
<para>
blah blah blah
</para>
</sect1>
</article>

8.3.2.�An example XML DocBook Book

DocBook books are generally for projects over 25 pages long, they allow the inclusion of chapters and parts, a book template is shown
below:

<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.2//EN"


"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<book>
<bookinfo>
<title>Your title here</title>
<author>
<firstname>Your first name</firstname>
<surname>Your surname</surname>
<affiliation>
<address><email>Your e-mail address</email></address>
</affiliation>
</author>
<copyright>
<year>1998</year>
<holder role="mailto:your e-mail address">Your name</holder>
</copyright>
<pubdate role="rcs">$Date: 2003/01/08 10:27:39 $</pubdate>
<releaseinfo>$Id: DocBookSys-Chapter8-XML-Creating.xml,v 1.1.1.1 2003/01/08 10:27:39 ug55axm
Exp $</releaseinfo>
<abstract>
<para>Include an abstract of the book&apos;s contents here.</para>
</abstract>
</bookinfo>
<part><title>Part1</title>
<chapter><title>Part 1, Chapter 1</title>
<sect1><title>Part1, Chapter 1, Section1</title>
<para>
Hello there!
<para>
</sect1>
</chapter>
<chapter><title>Part 1, Chapter 2</title>
<sect1><title>Part1, Chapter 2, Section 1</title>
<para>
Hi there!
<para>
</sect1>
</chapter>
</part>
<part><title>Part2</title>
<chapter><title>Part 2, Chapter 1</title>
<sect1><title>Part 2, Chapter 1, Section1</title>
<para>
GoodDay there!
<para>
</sect1>
<sect1><title>Part2, Chapter1, Section2</title>
<para>
GoodNight there!
<para>
</sect1>
</chapter>
</part>
</book>

This can be validated using xmllint like this:

xmllint --valid --nooutarticletemplatewin.xml

This should produce no errors and exit silently because the document is structured correctly. Chunked XHTML output can be
generated like this:

xsltproc file:///path/to/docbook-xsl/xhtml/chunk.dsl articletemplate.xml

There is a DocBook element quick reference card available from http://www.dpawson.co.uk/docbook/reference.html#d3e60.

Chapter�9.�DocBook Document Examples


Table of Contents

9.1. Common DocBook Elements


9.1.1. <para>
9.1.2. <programlisting>
9.1.3. Entities for special characters
9.1.4. <screen>
9.1.5. <ulink>
9.1.6. Lists

9.1.6.1. <itemizedlist>
9.1.6.2. <orderedlist>

9.1.7. Some common inline elements

9.2. Including Images


9.3. Tables

9.1.�Common DocBook Elements


9.1.1.�<para>

The reference page for the para element can be found here: http://www.docbook.org/tdg/en/html/para.html. para is one of the most
commonly used elements of all the DocBook elements. para's can contain block elements such as itemizedlist and mediaobject and can
contain almost all inline elements. There is some debate about whether or not it is best to separate block elements from para elements,
it is probably better to do so however because some processing systems have problems processing block elements within para
elements. An example of a para element containing some inline elements is shown below:

<para>
<quote>Behold the superfluous. They are always sick. They vomit their gall and call it
a newspaper.</quote>
- Friedrich Wilhelm Nietzsche, <citetitle>Twilight of the Idols</citetitle>
</para>

Looks like this:

“Behold the superfluous. They are always sick. They vomit their gall and call it a newspaper.” - Friedrich Wilhelm Nietzsche, Twilight
of the Idols

9.1.2.�<programlisting>

The reference page for the programlisting element can be found here: http://www.docbook.org/tdg/en/html/programlisting.html. The
programlisting element is used to display information that should be output verbatim, that is, white space is significant. An example is
shown below:

<programlisting>
public class HelloWorld {
public static void main(String args[]) {
System.out.println(&quot;Hello World!&quot;);
}
}
</programlisting>

Is output as:

public class HelloWorld {


public static void main(String args[]) {
System.out.println("Hello World!");
}
}
Notice the use of (&quot;) to represent the (") character, this is know as a character entity and is used to represent a character that is not
allowed to be used directly in the document, this is because these characters are used by the XML part of the document for special
purposes. These special characters are known as CDATA as apposed to PCDATA, the latter standing for Parsed Character DATA. If
one wants to use lots of CDATA characters in a document then one can wrap the section in a CDATA section like this:

<programlisting>
<![CDATA[
One can get away with using lots of &&& """ ''' <<< >>>
characters that would normally require being marked up as entities.
]]>
</programlisting>

Is displayed as:

One can get away with using lots of &&& """ ''' <<< >>> characters that would normally have
to be marked up as entities.

For more information about the available entities see the next section.

9.1.3.�Entities for special characters


The following entities are provided for special characters, they must always be used unless they are used in a section that has been
marked as a CDATA section. It is preferred to always use them in preference of CDATA sections however:

Character Entity
< &lt;
> &gt;
& &amp;
" &quot;
' &apos;

9.1.4.�<screen>

The reference page for the screen element can be found here: http://www.docbook.org/tdg/en/html/screen.html. Often one wants to
illustrate the use of a program or a commandline, the screen element is intended to mark content up as text that a user would see on a
computer screen. An example is shown below:

<screen>
<userinput><command>java</command> org.apache.fop.apps.Fop
<replaceable>in.fo</replaceable> <replaceable>out.pdf</replaceable></userinput>
</screen>

Is displayed as:

java org.apache.fop.apps.Fop in.fo out.pdf

9.1.5.�<ulink>

The reference page for the ulink element can be found here: http://www.docbook.org/tdg/en/html/ulink.html. ulink is the DocBook
equivalent of HTML's "<a href="...">blah blah</a>", an example is shown below:

<para>
<ulink url="http://www.oasis-open.org/committees/docbook/">http://www.oasis-
open.org/committees/docbook/</ulink>
</para>

Displays as:

http://www.oasis-open.org/committees/docbook/

9.1.6.�Lists

9.1.6.1.�<itemizedlist>

The reference page for itemizedlist is here: http://www.docbook.org/tdg/en/html/itemizedlist.html. Itemized lists are standard bulleted
lists and should be used where order of evaluation of the items of the list is not significant, ordered lists should be used where order of
evaluation fot he items of the list are significant. An example use of itemized list is shown below:

<itemizedlist>
<listitem><para>Books</para>
<itemizedlist>
<listitem><para>Donald E. Knuth - The Art Of Computer Programming</para>
</listitem>
<listitem><para>Nils J. Nilsson - Artificial Intelligence: A New Synthesis</para>
</listitem>
<listitem><para>Pure Mathematics 2 - Geoff Mannall, Michael Kenwood</para>
</listitem>
</itemizedlist>
</listitem>
<listitem><para>Games</para>
<itemizedlist>
<listitem><para>Chess</para></listitem>
<listitem><para>Backgammon</para></listitem>
<listitem><para>Noughs And Crosses</para></listitem>
</itemizedlist>
</listitem>
</itemizedlist>

Which looks like this:

Books

Donald E. Knuth - The Art Of Computer Programming

Nils J. Nilsson - Artificial Intelligence: A New Synthesis

Pure Mathematics 2 - Geoff Mannall, Michael Kenwood

Games

Chess

Backgammon

Noughs And Crosses

9.1.6.2.�<orderedlist>

The reference page for orderedlist is here: http://www.docbook.org/tdg/en/html/orderedlist.html. Ordered lists are used to specify a
sequence of steps of which the order of evaluation is significant. The general form of an ordered list is like this:

<orderedlist>
<listitem><para>Action A<para></listitem>
<listitem><para>Action B<para></listitem>
</orderedlist>
Which would look like this:

1. Action A

2. Action B

One may also specify the type of enumeration that the list will display, there are five types of enumeration; arabic, loweralpha,
lowerroman, upperalpha , upperroman. The type of enumeration is specified via the numeration attribute like this:

<orderedlist numeration="arabic">
<listitem>...</listitem>
.
.
.
</orderedlist>

The types of enumeration are shown below:

Arabic:

1. arabic

2. arabic

3. arabic

Loweralpha:

a. loweralpha

b. loweralpha

c. loweralpha

Lowerroman:

i. lowerroman

ii. lowerroman

iii. lowerroman

Upperalpha:

A. upperalpha

B. upperalpha

C. upperalpha

Upperroman:

I. upperroman

II. upperroman

III. upperroman

These can be combined to make nested enumeration clearer:

<orderedlist numeration="loweralpha">
<listitem>
<para>Preparation</para>
<orderedlist numeration="upperalpha">
<listitem><para>Chop tomatoes</para></listitem>
<listitem><para>Peel onions</para></listitem>
<listitem><para>Mash potatoes</para></listitem>
</orderedlist>
</listitem>
<listitem>
<para>Cooking</para>
<orderedlist numeration="upperalpha">
<listitem><para>Boil water</para></listitem>
<listitem><para>Put tomatoes and onions in</para></listitem>
<listitem><para>Blanch for 5 minutes</para></listitem>
</orderedlist>
</listitem>
<listitem>
<para>Cleanup</para>
<orderedlist numeration="upperalpha">
<listitem><para>Throw away scraps</para></listitem>
<listitem><para>Clean side</para></listitem>
<listitem><para>Wash hands</para></listitem>
</orderedlist>
</listitem>
</orderedlist>

Which looks like this:

I. Preparation

A. Chop tomatoes

B. Peel onions

C. Mash potatoes

II. Cooking

A. Boil water

B. Put tomatoes and onions in

C. Blanch for 5 minutes

III. Cleanup

A. Throw away scraps

B. Clean side

C. Wash hands

One may also make the enumeration continue at lower nested levels by setting the continuation attribute to continues:

<orderedlist>
<listitem>
<para>Do this</para>
<orderedlist numeration="arabic">
<listitem><para>And this</para></listitem>
<listitem><para>And this</para></listitem>
<listitem><para>And this</para></listitem>
</orderedlist>
</listitem>
<listitem>
<para>And this</para>
<orderedlist numeration="arabic" continuation="continues">
<listitem><para>And this</para></listitem>
<listitem><para>And this</para></listitem>
<listitem><para>And this</para></listitem>
</orderedlist>
</listitem>
</orderedlist>
Which looks like this:

1. Do this

1. And this

2. And this

3. And this

2. And this

4. And this

5. And this

6. And this

Note

Some stylesheets may define that nested lists are of a different numeration by default.

9.1.7.�Some common inline elements

Some common inline elements and their output are shown below:

Example Displays as
<emphasis>Emphasised Text</emphasis> Emphasised Text
<emphasis role="strong">A different type of emphasis</emphasis> A different type of emphasis
<filename>blahblah.txt</filename> blahblah.txt
<acronym>XML</acronym> XML
<quote>blahblahblah<quote> “blahblahblah”

9.2.�Including Images
Images are included in DocBook documents as illustrated below:

<figure><title>blah</title>
<mediaobject>
<imageobject><imagedata fileref="blah.jpg" format="JPEG"/></imageobject>
<textobject><phrase>Image description</phrase></textobject>
</mediaobject>
</figure>

The overall encapsulating element is figure the reference page for which can be found at
http://www.docbook.org/tdg/en/html/figure.html. The figure contains a mediaobject element which can occur on it's own too and may
contain audioobject, caption, imageobject, objectinfo, textobject and videoobject elements. The reference page formediaobject is at
http://www.docbook.org/tdg/en/html/mediaobject.html.

imageobject is the type of mediaobject used to include an image and it's reference page can be found at
http://www.docbook.org/tdg/en/html/imageobject.html. The item within the imageobject that handles the image is imagedata, it's
reference page is at http://www.docbook.org/tdg/en/html/imagedata.html.

The idea behind mediaobject is to provide a way to include media in many formats. It becomes the document processors job to decide
which of the formats specified in the mediaobject to use in the particular output medium chosen. For example the mediaobject element
may contain a PNG format imageobject for HTML output and a TIFF format imageobject for print output, there may also be a
textobject providing a description of the image for an output format that does not have the capability to display images, for example,
perhaps the document will be output in an audio format for people with sight problems.

One does not have to encapsulate the mediaobject in a figure object but doing so allows one to provide a title and be able to have the
figure listed in a list of figures at the beginning of the document.

imagedata may be of the following formats:

The attribute format is thus required along with either fileref or entityref to reference the image:

<mediaobject>
<imageobject><imagedata fileref="frog.png" format="PNG"/></imageobject>
<textobject><phrase>A frog</phrase></textobject>
</mediaobject>

One could use stylesheets such that, in HTML rendered output, the phrase used in the textobject would become the alternative text in
an image in the HTML. One can use multiple imageobjects for different output formats, for instance one may have an eps version of
the image so that output can be generated with a processing chain that requires the image to be in this form. One could include different
image formats for each of the desired output formats.

The imagedata element has the useful attributes align and valign. align specifies how the image should be aligned horizontally and can
be set to the values; center, left and right. valign specifies how the image should be aligned vertically and can be set to the values;
bottom, middle and top.

9.3.�Tables
There are two elements used for placing tables inside a DocBook document, table and informaltable, the only difference between the
former and the latter is that the former requires a title and the latter does not.

<table><title>title</title> <informaltable>
. .
. or .
. .
</table> </informaltable>

The table contains an attribute called frame which specifies how the table should be framed:

<table frame="frametype"><title>frame="frametype"</title>
<tgroup cols="1">
<thead>
<row><entry>a1</entry><entry>b1</entry><entry>c1</entry></row>
</thead>
<tbody>
<row><entry>a2</entry><entry>b2</entry><entry>c2</entry></row>
<row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
</tbody>
</tgroup>
</table>

Where frametype is replaced with one of all, bottom, none, sides, top or topbot:

Figure�9.1.�Table frame types

The output above is PDF, with HTML all the tables look the same as the one with attribute all apart from the one with attribute none
which has no frame at all. The attributes colsep and rowsep are used to control whether lines should be drawn between columns and
rows respectively:

<table colsep="0" rowsep="0"> ... </table>


<table colsep="0" rowsep="1"> ... </table>
<table colsep="1" rowsep="0"> ... </table>
<table colsep="1" rowsep="1"> ... </table>

Unfortunately at the time of writing the tools used to convert FO to PDF either did not yet implement this feature or were in a broken
state with regards to this feature so no pictorial examples can be provided. Other table attributes are discussed at
http://www.docbook.org/tdg/en/html/table.html.

The generic layout for a table is as follows:

<table><title>title</title>
<tgroup cols="3">
<thead>
<row><entry>blah</entry></row>
</thead>
<tbody>
<row><entry>blah</entry></row>
</tbody>
<tfoot>
<row><entry>blah</entry></row>
</tfoot>
</tgroup>
</table>

tgroup contains the rest of the table which must contain a tbody element which specifies which data is in the body of the table. The
tbody element may be empty with the table being included in thead or tfoot but this is not the intention. The reason for the thead and
tfoot elements is so that different layouts can be applied by the stylesheets for the header and the footer of the table respectively. So
usually the first row would be wrapped in a thead element. tgroup has the mandatory attribute cols which specifies the number of
columns the table has.

tgroup may also specify alignment of content via the align attribute, where alignment is either left, center or right:
<table frame="all"><title>align="alignment"</title>
<tgroup cols="3" align="alignment">
<tbody>
<row><entry>a2</entry><entry>b2</entry><entry>c2</entry></row>
</tbody>
</tgroup>
</table>

Figure�9.2.�Table alignment types

For more information about the tgroup element see http://www.docbook.org/tdg/en/html/tgroup.html.

A row consists of a number of entry elements which are entered in the sequence they should appear in each table row, for more
information about the row element see http://www.docbook.org/tdg/en/html/row.html.

The entry element has some interesting attributes which allow an entry to span more than one column or row, they are (namest &
nameend) and morerows respectively. The morerow attribute specifies how many more rows the entry it is applied to should span:

<table frame="all"><title><emphasis>morerows</emphasis> example</title>


<tgroup cols="3">
<tbody>
<row><entry morerows="2">a1</entry><entry>b1</entry><entry>c1</entry></row>
<row><entry>b2</entry><entry>c2</entry></row>
<row><entry>b3</entry><entry>c3</entry></row>
</tbody>
</tgroup>
</table>

Figure�9.3.�morerows example

Unfortunately there is no morecolumns attribute, instead one has to use namest to specify the starting column of the entry and nameend
to specify the ending column of the entry. The value applied to this attribute is the name of the columns, columns are named using the
colspec element, colspec elements are inserted inside tgroup but before thead, tbody and tfoot:

<table frame="all"><title>column spanning</title>


<tgroup cols="3">
<colspec colname="col1"/>
<colspec colname="col2"/>
<colspec colname="col3"/>
<tbody>
<row><entry namest="col1" nameend="col3">a1</entry></row>
<row><entry>a2</entry><entry>b1</entry><entry>c1</entry></row>
<row><entry>a3</entry><entry>b2</entry><entry>c2</entry></row>
</tbody>
</tgroup>
</table>

Figure�9.4.�Column spanning example

More information about the entry element can be found at http://www.docbook.org/tdg/en/html/entry.html. Tables may be nested to a
level of one, see http://www.docbook.org/tdg/en/html/entrytbl.html. For the entire source and output pertaining to the examples
discussed in this section see Table Examples.

Chapter�10.�Auxiliary Tools for DocBook Authoring


Table of Contents

10.1. Editors

10.1.1. VI/VIM/GVIM
10.1.2. Emacs
10.1.3. ThotBook
10.1.4. EpcEdit
10.1.5. Xeena
10.1.6. The rest

10.2. Spell Checking

10.2.1. Aspell

10.1.�Editors
One of the most important parts of any DocBook authoring suite is the editing environment since this is where the author spend most of
the time in the document production process. It is possible to author DocBook documents in a plain text editor but this does not give
the user the benefits as syntax highlighting, auto-indentation and spell-checking. Therefore it is imperative to find an editor that is
comfortable and maximises productivity.

10.1.1.�VI/VIM/GVIM

http://vim.sourceforge.net/

Vi is only available on Unix. Vim works on MS-Windows, Macintosh, Amiga, OS/2, VMS, QNX and other systems. And
also on every Unix system. Vim offers syntax highlighting for over 200 languages. And if that's not enough, you can
define your own syntax. Vim is free! It is open source with a charityware license.

VIM which stands for vi improved is a vast improvement on the original Unix editor, GUI version is called GVIM. This is the editor
that I personally use as I personally feel comfortable with its speed and utility. It has syntax highlighting for XML and SGML modes.
It has a relatively steep learning curve however and takes a while to get reasonably proficient at for most people. But VIM also has an
"easy" mode which makes it feel like your typical "dumb" editor yet it still has all the power of VIM behind it.

Figure�10.1.�GVIM screen-shot
10.1.2.�Emacs

http://www.gnu.org/software/emacs/emacs.html

To quote the Emacs Manual: “Emacs is the extensible, customizable, self-documenting real-time display editor.” Emacs (name derived
from Editor MACroS), is a text editor with an emacs lisp core. It is easier than Vi to get started with and it is also the editor of choice
for many Universities and educational institutes, there have been many a flame war over the issue of VI vs EMACS. It has a PSGML
mode which can be setup to author DocBook with syntax highlighting and Norman Walsh has produced a DocBook IDE major mode
which incorporates extensive features such as automatic completion of end tags and insertion of elements. Emacs has an ispell/Aspell
plug-in to enable spell checking on-the-fly. It is available for just about any operating system. GUI capable versions are available.
Emacs is released under the GPL (its free).

Figure�10.2.�Emacs screen-shot
10.1.3.�ThotBook

http://www.freesoftware.fsf.org/thotbook/

To quote the FAQ:

ThotBook is (will be) a visual editor for DocBook, based on ThotLib. ThotBook will allow users to visually edit DocBook
documents using a graphical interface and will allow them to import/export their work into structured DocBook
SGML/XML. ThotBook will help to produce valid structured DocBook documents without having to learn the DocBook
syntax. ThotBook will respect document structure, as opposed to "WYSIWYG" editors, which produce (mostly)
unstructured documents.

It is only available via CVS at the moment but should be one to watch for users who like visual interfaces.

Figure�10.3.�ThotBook screen-shot
10.1.4.�EpcEdit
http://www.epcedit.com/

EpcEdit is a commercial GUI editor for Unix and Windows, it has many features such as integrated enhanced validating XML/SGML
parser, to quote the website:

epcEdit provides a structure-sensitive view of XML or SGML documents and allows editing of a document while keeping
it in conformance with the document's DTD. An integrated table editor helps in visualizing the layout of tables conforming
to the CALS or HTML table models. The hierarchical structure of a document is represented by a tree view that is updated
while the document changes.

Figure�10.4.�EpcEdit screen-shot
10.1.5.�Xeena

http://www.alphaworks.ibm.com/tech/xeena

Xeena, a visual XML editor, is a generic Java application for editing valid XML documents derived from any valid DTD.
XML files can be created and edited without learning the intricacies of XML. The editor takes as input a given DTD and
automatically builds a palette containing the elements defined in the DTD. Any document derived from that DTD by using
a visual, tree-directed paradigm can thus be created, edited, or expanded. The visual paradigm requires only a minimal
learning curve, because only valid constructs or elements are presented to the user in a context-sensitive palette.

The above quote is according to the website, I installed it and tried it out and it looked OK but I took it no further. As far as licensing
goes, it appears that the software is free for "Independent development", but what this means is unknown by me at the moment. It is
platform independent.

Figure�10.5.�Xeena screen-shot
10.1.6.�The rest

There are quite a few editors available and there is likely to be a lot more in the future. Keep an eye out. Here is a short list of some
others, all descriptions are taken from the websites indicated, all rights reserved.

http://www.morphon.com/xmleditor/index.shtml

The Morphon XML-Editor is a validating XML-Editor which lets you easily create and modify XML documents. Morphon also
provides a CSS editor for use as a styling language. The Editor itself is able to run on the maximum number of platforms as it is
written in Java, and uses the Java Foundation Classes (JFC) Libraries.

http://www.xmlmind.com/xmleditor/

XMLmind XML Editor (XXE for short) is an XML editor featuring DTD-aware editing commands and a word processor-like
view configured using W3C's cascading style-sheets (CSS).

http://fabrice.bellard.free.fr/qemacs/

QEmacs (for Quick Emacs) is a very small but powerful UNIX editor....WYSIWYG DocBook mode based on XML/CSS2
renderer.

10.2.�Spell Checking
Since a DocBook document is full of tags it can be quite hard to check the spelling of such a document without having the spell-
checker constantly complain. Fortunately there are spell-checkers available out there that can ignore tags.

10.2.1.�Aspell

http://aspell.sourceforge.net/

Aspell is an Open Source spell checker designed to eventually replace Ispell. Its main feature is that it does a superior job
of coming up with suggestions than just about any other spell checker out there for the English language.
It is available for both Unix and Windows, and while integration into editing environments is possible, it is possible to use it
standalone. One can easily spell check a DocBook file with the following command sequence.

aspell --mode=sgml check in.xml/sgml

This will bring up a spell checking program with the usual choices of adding to the dictionary, replacing all occurrences of a word and
so on. The SGML mode works for both SGML and XML documents. And there are dictionaries for about 16 or so different languages
excluding the standard British or American English language packs.

Figure�10.6.�Aspell screen-shot

Chapter�11.�References
Table of Contents

11.1. Internet Resources Used

11.1.�Internet Resources Used


Thanks goto all the people who helped me when I was stuck.

http://www.docbook.org/tdg/en/html/docbook.html

DocBook:�The�Definitive�Guide
by�Norman�Walsh�and�Leonard�Muellner
With�contributions�from�Bob�Stayton
ISBN:�156592-580-7
Version�2.0.6
Updated:�Wed,�12�Jun�2002

Copyright�1999,�2000,�2001,�2002�O'Reilly�&�Associates,�Inc.�All�rights�reserved.
����������

http://ourworld.compuserve.com/homepages/hoenicka_markus/ntsgml.html

SGML for NT: A brief tutorial how to set up a free SGML/XML editing and publishing system for Windows

http://www.dpawson.co.uk/docbook/index.html
Docbook Frequently Asked Questions

http://www.bureau-cornavin.com/opensource/crash-course/index.html

DocBook�XML�4.1.2�Quick�Start�Guide
Jim�Weller
Sleepless�Tech

[email protected]

Copyright�2001�by�Jim�Weller

2001-05-29
����������

http://nis-www.lanl.gov/~rosalia/mydocs/docbook-intro.html

Get�Going�With�DocBook
Notes�for�Hackers
Mark�Galassi
Cygnus�Solutions

Copyright�1998�by�Mark�Galassi
����������

http://people.freebsd.org/~nik/nwalsh/Customising%20the%20nwalsh%20DSSSL%20stylesheets_files/v3_document.htm

Customising the nwalsh DSSSL stylesheets [email protected]

http://old.lwn.net/2000/features/DocBook/

Exploring�SGML�DocBook
April�24,�2000
Giorgio�Zoppi
����������

http://cyberelk.net/tim/docbook/selfdocbook/selfdocbook.html

Selfdocbook
Tim�Waugh
Red�Hat,�Inc.

������[email protected]��

Copyright�2000-2�by�Tim�Waugh ��
����������

http://www.oasis-open.org/cover/general.html

The�XML�Cover�Pages�
SGML:�General�Introductions�and�Overviews�
By:�Robin�Cover�

Last�modified:�June�28,�1999 ��
����������

http://www.sagehill.net/xml/docbookxsl/index.html
Robert�Stayton
<[email protected]>

Draft�--�7�July�2002

Copyright�2002�Robert�Stayton
����������

http://www.ibiblio.org/pub/sun-info/standards/xml/why/xmlapps.htm

XML,�Java,�and�the�future�of�the�Web
Jon�Bosak,�Sun�Microsystems
Last�revised�1997.03.10�
����������

http://www.ibiblio.org/godoy/sgml/docbook/howto/

DocBook�HOWTO
Jorge�Godoy
Conectiva�S.A.
Publishing�Department

[email protected]
����������

http://www.w3.org/TR/NOTE-sgml-xml

Comparison�of�SGML�and�XML
World�Wide�Web�Consortium�Note�15-December-1997�
����������

http://docbook.sourceforge.net/release/dsssl/current/doc/

The�Modular�DocBook�Stylesheets
Norman�Walsh
Copyright�1997,�1998,�1999,�2000�by�Norman�Walsh
����������

http://docbook.sourceforge.net/release/xsl/current/doc/

DocBook�XSL�Stylesheet�Documentation
Norman�Walsh
Bob�Stayton

Jiri�Kosek

Copyright�1999,�2000,�2001,�2002�Norman�Walsh.�No�Warranty
����������

http://www.tldp.org/LDP/LDP-Author-Guide/

LDP�Author�Guide
Mark�F.�Komarinski
[email protected]
Jorge�Godoy
Conectiva�S.A.
Publishing�Department

[email protected]

[email protected]

David�C.�Merrill
[email protected]
���������

http://www.freebsd.org/doc/en_US.ISO8859-1/books/fdp-primer/

FreeBSD�Documentation�Project�Primer�for�New�Contributors
Nik�Clayton
[email protected]

Copyright�1998,�1999,�2000,�2001,�2002�by�Nik�Clayton
����������

http://www.tldp.org/HOWTO/mini/DocBook-Install/index.html

DocBook�Install�mini-HOWTO
Robert�B�Easter
[email protected]
����������

http://sources.redhat.com/ml/docbook-apps/

The docbook-apps mailing list archives


Tutorials  Featured  .NET Magazines About  Developer Tools

LINQ To XML Tutorials with Examples


Posted by: Suprotim Agarwal , on 8/29/2010, in Category LINQ
Abstract: In this article, we will learn LINQ To XML using some ‘How Do I’ kind of examples.
Views: 541595

A lot of developers over the past few months have requested us for tutorials focusing on LINQToXML. Although I
have written a couple of them in the past, I decided to republish these tips in the form of a single post. In this
article, we will explore 24 ‘How Do I’ kind of examples using LINQ to XML. I assume you are familiar with LINQ.
If not, you can start off with LINQ by checking some tutorials over here and here.

For this article, we will be using a sample file called ‘Employees.xml’ for all our samples which is available with
the source code. So make sure you keep it handy with you while are practicing these examples. The mark up
for Employees.xml is as follows:

<?xml version="1.0" encoding="utf-8" ?>


<Employees>
<Employee>
    <EmpId>1</EmpId>
    <Name>Sam</Name>   
    <Sex>Male</Sex>
    <Phone Type="Home">423-555-0124</Phone>
    <Phone Type="Work">424-555-0545</Phone>
   <Address>
      <Street>7A Cox Street</Street>
      <City>Acampo</City>
      <State>CA</State>
      <Zip>95220</Zip>
      <Country>USA</Country>
    </Address>
</Employee>
<Employee>
    <EmpId>2</EmpId>
    <Name>Lucy</Name>
    <Sex>Female</Sex>
    <Phone Type="Home">143-555-0763</Phone>
    <Phone Type="Work">434-555-0567</Phone>
    <Address>
      <Street>Jess Bay</Street>
      <City>Alta</City>
      <State>CA</State>
      <Zip>95701</Zip>
      <Country>USA</Country>
    </Address>
</Employee>
<Employee>
    <EmpId>3</EmpId>
    <Name>Kate</Name>
    <Sex>Female</Sex>
    <Phone Type="Home">166-555-0231</Phone>
    <Phone Type="Work">233-555-0442</Phone>
    <Address>
      <Street>23 Boxen Street</Street>
      <City>Milford</City>
      <State>CA</State>
      <Zip>96121</Zip>
      <Country>USA</Country>
    </Address>
</Employee>
<Employee>
    <EmpId>4</EmpId>
    <Name>Chris</Name>
    <Sex>Male</Sex>
    <Phone Type="Home">564-555-0122</Phone>
    <Phone Type="Work">442-555-0154</Phone>
    <Address>
      <Street>124 Kutbay</Street>
      <City>Montara</City>
      <State>CA</State>
      <Zip>94037</Zip>
      <Country>USA</Country>
    </Address>
</Employee>
</Employees>

The application is a console application targeting .NET 3.5 framework, although you can use the latest .NET 4.0
framework too. I have also used ‘query expressions’, instead of Lambda expression in these samples. It is just a
matter of preference and you are free to use any of these.

This tutorial has been divided into 2 sections:

Section 1: Read XML and Traverse the Document using LINQ To XML

Section 2: Manipulate XML content and Persist the changes using LINQ To XML

The following namespaces are needed while testing the samples: System; System.Collections.Generic;
System.Linq; System.Text; System.Xml; System.Xml.Linq;

Go grab a hot cup of coffee, put on your developer cap and let us get started:

Section 1: Read XML and Traverse the XML Document using LINQ To XML
1. How Do I Read XML using LINQ to XML

There are two ways to do so: Using the XElement class or the XDocument class. Both the classes contain the
‘Load()’ method which accepts a file, a URL or XMLReader and allows XML to be loaded. The primary difference
between both the classes is that an XDocument can contain XML declaration, XML Document Type (DTD) and
processing instructions. Moreover an XDocument contains one root XElement.

Using XElement

C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


IEnumerable<XElement> employees = xelement.Elements();
// Read the entire XML
foreach (var employee in employees)
{
    Console.WriteLine(employee);
}

VB.NET (Converted Code)

Dim xelement As XElement = XElement.Load("..\..\Employees.xml")


Dim employees As IEnumerable(Of XElement) = xelement.Elements()
' Read the entire XML
For Each employee In employees
      Console.WriteLine(employee)
Next employee

Output:

Using XDocument

C#

XDocument xdocument = XDocument.Load("..\\..\\Employees.xml");


IEnumerable<XElement> employees = xdocument.Elements();
foreach (var employee in employees)
{
    Console.WriteLine(employee);
}

VB.NET (Converted Code)

Dim xdocument As XDocument = XDocument.Load("..\..\Employees.xml")


Dim employees As IEnumerable(Of XElement) = xdocument.Elements()
For Each employee In employees
      Console.WriteLine(employee)
Next employee

Output:

Note 1: As you can observe, XDocument contains a single root element (Employees).

Note 2: In order to generate an output similar to the one using XElement, use “xdocument.Root.Elements()”
instead of “xdocument.Elements()”

Note 3: VB.NET users can use a new feature called XML Literal.

2. How Do I Access a Single Element using LINQ to XML

Let us see how to access the name of all the Employees and list them over here

C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


IEnumerable<XElement> employees = xelement.Elements();
Console.WriteLine("List of all Employee Names :");
foreach (var employee in employees)
{
    Console.WriteLine(employee.Element("Name").Value);
}

VB.NET (Converted Code)

Dim xelement As XElement = XElement.Load("..\..\Employees.xml")


Dim employees As IEnumerable(Of XElement) = xelement.Elements()
Console.WriteLine("List of all Employee Names :")
For Each employee In employees
      Console.WriteLine(employee.Element("Name").Value)
Next employee

Output:
3. How Do I Access Multiple Elements using LINQ to XML

Let us see how to access the name of all Employees and also list the ID along with it

C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


IEnumerable<XElement> employees = xelement.Elements();
Console.WriteLine("List of all Employee Names along with their ID:");
foreach (var employee in employees)
{
    Console.WriteLine("{0} has Employee ID {1}",
        employee.Element("Name").Value,
        employee.Element("EmpId").Value);
}
VB.NET (Converted Code)

Dim xelement As XElement = XElement.Load("..\..\Employees.xml")


Dim employees As IEnumerable(Of XElement) = xelement.Elements()
Console.WriteLine("List of all Employee Names along with their ID:")
For Each employee In employees
      Console.WriteLine("{0} has Employee ID {1}", employee.Element("Name").Value,
employee.Element("EmpId").Value)
Next employee

Output:

4. How Do I Access all Elements having a Specific Attribute using LINQ to XML

Let us see how to access details of all Female Employees

C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


var name = from nm in xelement.Elements("Employee")
           where (string)nm.Element("Sex") == "Female"
           select nm;
Console.WriteLine("Details of Female Employees:");
foreach (XElement xEle in name)
    Console.WriteLine(xEle);

VB.NET (Converted Code)

Dim xelement As XElement = XElement.Load("..\..\Employees.xml")


Dim name = _
      From nm In xelement.Elements("Employee") _
      Where CStr(nm.Element("Sex")) = "Female" _
      Select nm
Console.WriteLine("Details of Female Employees:")
For Each xEle As XElement In name
      Console.WriteLine(xEle)
Next xEle

Output:

5. How Do I access Specific Element having a Specific Attribute using LINQ to XML

Let us see how to list all the Home Phone Nos.

C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


var homePhone = from phoneno in xelement.Elements("Employee")
                where (string)phoneno.Element("Phone").Attribute("Type") == "Home"
                select phoneno;
Console.WriteLine("List HomePhone Nos.");
foreach (XElement xEle in homePhone)
{
    Console.WriteLine(xEle.Element("Phone").Value);
}

VB.NET (Converted Code)

Dim xelement As XElement = XElement.Load("..\..\Employees.xml")


Dim homePhone = _
      From phoneno In xelement.Elements("Employee") _
      Where CStr(phoneno.Element("Phone").Attribute("Type")) = "Home" _
      Select phoneno
Console.WriteLine("List HomePhone Nos.")
For Each xEle As XElement In homePhone
      Console.WriteLine(xEle.Element("Phone").Value)
Next xEle

Output:

6. How Do I Find an Element within another Element using LINQ to XML

Let us see how to find the details of Employees living in 'Alta' City
C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


var addresses = from address in xelement.Elements("Employee")
                where (string)address.Element("Address").Element("City") == "Alta"
               select address;
Console.WriteLine("Details of Employees living in Alta City");
foreach (XElement xEle in addresses)
    Console.WriteLine(xEle);

VB.NET (Converted Code)

Dim xelement As XElement = XElement.Load("..\..\Employees.xml")


Dim addresses = _
      From address In xelement.Elements("Employee") _
      Where CStr(address.Element("Address").Element("City")) = "Alta" _
      Select address
Console.WriteLine("Details of Employees living in Alta City")
For Each xEle As XElement In addresses
      Console.WriteLine(xEle)
Next xEle

Output:

7. How Do I Find Nested Elements (using Descendants Axis) using LINQ to XML

Let us see how to list all the zip codes in the XML file

C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


Console.WriteLine("List of all Zip Codes");
foreach (XElement xEle in xelement.Descendants("Zip"))
{
    Console.WriteLine((string)xEle);
}

VB.NET (Converted Code)

Dim xelement As XElement = XElement.Load("..\..\Employees.xml")


Console.WriteLine("List of all Zip Codes")
For Each xEle As XElement In xelement.Descendants("Zip")
      Console.WriteLine(CStr(xEle))
Next xEle
Output:

8. How do I apply Sorting on Elements using LINQ to XML

Let us see how to List and Sort all Zip Codes in ascending order

C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


IEnumerable<string> codes = from code in xelement.Elements("Employee")
                            let zip = (string)code.Element("Address").Element("Zip")
                            orderby zip
                            select zip;
Console.WriteLine("List and Sort all Zip Codes");

foreach (string zp in codes)


    Console.WriteLine(zp);

VB.NET (Converted Code)

Dim xelement As XElement = XElement.Load("..\..\Employees.xml")


Dim codes As IEnumerable(Of String) = _
      From code In xelement.Elements("Employee") _
      Let zip = CStr(code.Element("Address").Element("Zip")) _
      Order By zip _
      Select zip
Console.WriteLine("List and Sort all Zip Codes")

For Each zp As String In codes


      Console.WriteLine(zp)
Next zp

Output:

Section 2: Manipulate XML content and Persist the changes using LINQ To XML

9. Create an XML Document with Xml Declaration/Namespace/Comments using LINQ to XML

When you need to create an XML document containing XML declaration, XML Document Type (DTD) and
processing instructions, Comments, Namespaces, you should go in for the XDocument class.

C#
XNamespace empNM = "urn:lst-emp:emp";

XDocument xDoc = new XDocument(


            new XDeclaration("1.0", "UTF-16", null),
            new XElement(empNM + "Employees",
                new XElement("Employee",
                    new XComment("Only 3 elements for demo purposes"),
                    new XElement("EmpId", "5"),
                    new XElement("Name", "Kimmy"),
                    new XElement("Sex", "Female")
                    )));

StringWriter sw = new StringWriter();


xDoc.Save(sw);
Console.WriteLine(sw);

VB.NET (Converted Code)

        Dim empNM As XNamespace = "urn:lst-emp:emp"

        Dim xDoc As New XDocument(New XDeclaration("1.0", "UTF-16", Nothing), _


                    New XElement(empNM + "Employees", _
                    New XElement("Employee", _
                    New XComment("Only 3 elements for demo purposes"), _
                    New XElement("EmpId", "5"), _
                    New XElement("Name", "Kimmy"), _
                    New XElement("Sex", "Female"))))

        Dim sw As New StringWriter()


        xDoc.Save(sw)
        Console.WriteLine(sw)

10. Save the XML Document to a XMLWriter or to the disk using LINQ to XML

Use the following code to save the XML to a XMLWriter or to your physical disk

C#

XNamespace empNM = "urn:lst-emp:emp";

XDocument xDoc = new XDocument(


            new XDeclaration("1.0", "UTF-16", null),
            new XElement(empNM + "Employees",
                new XElement("Employee",
                    new XComment("Only 3 elements for demo purposes"),
                    new XElement("EmpId", "5"),
                    new XElement("Name", "Kimmy"),
                    new XElement("Sex", "Female")
                    )));

StringWriter sw = new StringWriter();


XmlWriter xWrite = XmlWriter.Create(sw);
xDoc.Save(xWrite);
xWrite.Close();

// Save to Disk
xDoc.Save("C:\\Something.xml");
Console.WriteLine("Saved");

VB.NET (Converted Code)

       Dim empNM As XNamespace = "urn:lst-emp:emp"

Dim xDoc As New XDocument(New XDeclaration("1.0", "UTF-16", Nothing),_


        New XElement(empNM + "Employees", _
        New XElement("Employee", _
        New XComment("Only 3 elements for demo purposes"), _
       New XElement("EmpId", "5"), _
        New XElement("Name", "Kimmy"), _
        New XElement("Sex", "Female"))))

        Dim sw As New StringWriter()


        Dim xWrite As XmlWriter = XmlWriter.Create(sw)
        xDoc.Save(xWrite)
        xWrite.Close()

        ' Save to Disk


        xDoc.Save("C:\Something.xml")
        Console.WriteLine("Saved")

11. Load an XML Document using XML Reader using LINQ to XML

Use the following code to load the XML Document into an XML Reader

C#

XmlReader xRead = XmlReader.Create(@"..\\..\\Employees.xml");


XElement xEle = XElement.Load(xRead);
Console.WriteLine(xEle);
xRead.Close();

VB.NET (Converted Code)

Dim xRead As XmlReader = XmlReader.Create("..\\..\\Employees.xml")


Dim xEle As XElement = XElement.Load(xRead)
Console.WriteLine(xEle)
xRead.Close()
12. Find Element at a Specific Position using LINQ to XML

Find the 2nd Employee Element

C#

// Using XElement
Console.WriteLine("Using XElement");
XElement xEle = XElement.Load("..\\..\\Employees.xml");
var emp1 = xEle.Descendants("Employee").ElementAt(1);
Console.WriteLine(emp);

Console.WriteLine("------------");

//// Using XDocument


Console.WriteLine("Using XDocument");
XDocument xDoc = XDocument.Load("..\\..\\Employees.xml");
var emp1 = xDoc.Descendants("Employee").ElementAt(1);
Console.WriteLine(emp);

VB.NET (Converted Code)

' Using XElement


Console.WriteLine("Using XElement")
Dim xEle As XElement = XElement.Load("..\..\Employees.xml")
Dim emp1 = xEle.Descendants("Employee").ElementAt(1)
Console.WriteLine(emp)

Console.WriteLine("------------")

'// Using XDocument


Console.WriteLine("Using XDocument")
Dim xDoc As XDocument = XDocument.Load("..\..\Employees.xml")
Dim emp1 = xDoc.Descendants("Employee").ElementAt(1)
Console.WriteLine(emp)
13. List the First 2 Elements using LINQ to XML

List the details of the first 2 Employees

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


var emps = xEle.Descendants("Employee").Take(2);
foreach (var emp in emps)
    Console.WriteLine(emp);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


Dim emps = xEle.Descendants("Employee").Take(2)
For Each emp In emps
      Console.WriteLine(emp)
Next emp
14. List the 2nd and 3rd Element using LINQ to XML

List the 2nd and 3rd Employees

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


var emps = xEle.Descendants("Employee").Skip(1).Take(2);
foreach (var emp in emps)
    Console.WriteLine(emp);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


Dim emps = xEle.Descendants("Employee").Skip(1).Take(2)
For Each emp In emps
      Console.WriteLine(emp)
Next emp

15. List the Last 2 Elements using LINQ To XML

We have been posting the entire elements as output in our previous examples. Let us say that you want to
display only the Employee Name, use this query:

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


var emps = xEle.Descendants("Employee").Reverse().Take(2);
foreach (var emp in emps)
    Console.WriteLine(emp.Element("EmpId") + "" + emp.Element("Name"));

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


Dim emps = xEle.Descendants("Employee").Reverse().Take(2)
For Each emp In emps
      Console.WriteLine(emp.Element("EmpId") + emp.Element("Name"))
Next emp
To display only the values without the XML tags, use the ‘Value’ property

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


var emps = xEle.Descendants("Employee").Reverse().Take(2);
foreach (var emp in emps)
    Console.WriteLine(emp.Element("EmpId").Value + ". " + emp.Element("Name").Value);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


Dim emps = xEle.Descendants("Employee").Reverse().Take(2)
For Each emp In emps
      Console.WriteLine(emp.Element("EmpId").Value & ". " & emp.Element("Name").Value)
Next emp

If you notice, the results are not ordered i.e. the Employee 4 is printed before 3. To order the results, just add
call Reverse() again while filtering as shown below:

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


var emps = xEle.Descendants("Employee").Reverse().Take(2).Reverse();
foreach (var emp in emps)
    Console.WriteLine(emp.Element("EmpId").Value + ". " + emp.Element("Name").Value);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


Dim emps = xEle.Descendants("Employee").Reverse().Take(2).Reverse()
For Each emp In emps
      Console.WriteLine(emp.Element("EmpId").Value & ". " & emp.Element("Name").Value)
Next emp

16. Find the Element Count based on a condition using LINQ to XML

Count the number of Employees living in the state CA

C#

XElement xelement = XElement.Load("..\\..\\Employees.xml");


var stCnt = from address in xelement.Elements("Employee")
            where (string)address.Element("Address").Element("State") == "CA"
            select address;
Console.WriteLine("No of Employees living in CA State are {0}", stCnt.Count());

VB.NET (Converted Code)

XElement xelement = XElement.Load("..\\..\\Employees.xml");


var stCnt = from address in xelement.Elements("Employee")
            where (string)address.Element("Address").Element("State") == "CA"
            select address;
Console.WriteLine("No of Employees living in CA State are {0}", stCnt.Count());

17. Add a new Element at runtime using LINQ to XML

You can add a new Element to an XML document at runtime by using the Add() method of XElement. The new
Element gets added as the last element of the XML document.

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


xEle.Add(new XElement("Employee",
     new XElement("EmpId", 5),
    new XElement("Name", "George")));

Console.Write(xEle);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


        xEle.Add(New XElement("Employee", _
                              New XElement("EmpId", 5), _
                              New XElement("Name", "George")))

Console.Write(xEle)

18. Add a new Element as the First Child using LINQ to XML

In the previous example, by default the new Element gets added to the end of the XML document. If you want to
add the Element as the First Child, use the ‘AddFirst()’ method

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


    xEle.AddFirst(new XElement("Employee",
        new XElement("EmpId", 5),
        new XElement("Name", "George")));

    Console.Write(xEle);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


   xEle.AddFirst(New XElement("Employee", _
      New XElement("EmpId", 5), _
      New XElement("Name", "George")))

Console.Write(xEle)

19. Add an attribute to an Element using LINQ to XML

To add an attribute to an Element, use the following code:

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


    xEle.Add(new XElement("Employee",
        new XElement("EmpId", 5),
        new XElement("Phone", "423-555-4224", new XAttribute("Type", "Home"))));

    Console.Write(xEle);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


        xEle.Add(New XElement("Employee", _
                              New XElement("EmpId", 5), _
                              New XElement("Phone", "423-555-4224", _
                                           New XAttribute("Type", "Home"))))

        Console.Write(xEle)

20. Replace Contents of an Element/Elements using LINQ to XML

Let us say that in the XML file, you want to change the Country from “USA” to “United States of America” for all
the Elements. Here’s how to do so:

C#
XElement xEle = XElement.Load("..\\..\\Employees.xml");
    var countries = xEle.Elements("Employee").Elements("Address").Elements("Country").ToList();
    foreach (XElement cEle in countries)
        cEle.ReplaceNodes("United States Of America");

    Console.Write(xEle);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


        Dim countries =
xEle.Elements("Employee").Elements("Address").Elements("Country").ToList()
        For Each cEle As XElement In countries
            cEle.ReplaceNodes("United States Of America")
        Next cEle

Console.Write(xEle)

21. Remove an attribute from all the Elements using LINQ to XML

Let us say if you want to remove the Type attribute ( <Phone Type=”Home”>) attribute for all the elements,
then here’s how to do it.

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


    var phone = xEle.Elements("Employee").Elements("Phone").ToList();
    foreach (XElement pEle in phone)
        pEle.RemoveAttributes();

    Console.Write(xEle);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


        Dim phone = xEle.Elements("Employee").Elements("Phone").ToList()
        For Each pEle As XElement In phone
            pEle.RemoveAttributes()
        Next pEle

Console.Write(xEle)

To remove attribute of one Element based on a condition, traverse to that Element


and SetAttributeValue("Type", null); You can also use SetAttributeValue(XName,object) to update an attribute
value.

22. Delete an Element based on a condition using LINQ to XML

If you want to delete an entire element based on a condition, here’s how to do it. We are deleting the entire
Address Element

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


    var addr = xEle.Elements("Employee").ToList();
    foreach (XElement addEle in addr)
        addEle.SetElementValue("Address", null);

    Console.Write(xEle);

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


    Dim addr = xEle.Elements("Employee").ToList()
        For Each addEle As XElement In addr
            addEle.SetElementValue("Address", Nothing)
        Next addEle

Console.Write(xEle)
SetElementValue() can also be used to Update the content of an Element.

23. Remove ‘n’ number of Elements using LINQ to XML

If you have a requirement where you have to remove ‘n’ number of Elements; For E.g. To remove the last 2
Elements, then here’s how to do it

C#

XElement xEle = XElement.Load("..\\..\\Employees.xml");


    var emps = xEle.Descendants("Employee");
    emps.Reverse().Take(2).Remove();

    Console.Write(xEle);

VB.NET (Converted Code)

       Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


        Dim emps = xEle.Descendants("Employee")
        emps.Reverse().Take(2).Remove()

        Console.Write(xEle)

24. Save/Persists Changes to the XML using LINQ to XML

All the manipulations we have done so far were in the memory and were not persisted in the XML file. If you
have been wondering how to persist changes to the XML, once it is modified, then here’s how to do so. It’s quite
simple. You just need to call the Save() method. It’s also worth observing that the structure of the code shown
below is similar to the structure of the end result (XML document). That’s one of the benefits of LINQ to XML,
that it makes life easier for developers by making it so easy to create and structure XML documents.

C#

    XElement xEle = XElement.Load("..\\..\\Employees.xml");


    xEle.Add(new XElement("Employee",
    new XElement("EmpId", 5),
    new XElement("Name", "George"),
    new XElement("Sex", "Male"),
    new XElement("Phone", "423-555-4224", new XAttribute("Type", "Home")),
    new XElement("Phone", "424-555-0545", new XAttribute("Type", "Work")),
    new XElement("Address",
        new XElement("Street", "Fred Park, East Bay"),
        new XElement("City", "Acampo"),
        new XElement("State", "CA"),
        new XElement("Zip", "95220"),
        new XElement("Country", "USA"))));

    xEle.Save("..\\..\\Employees.xml");
    Console.WriteLine(xEle);

    Console.ReadLine();         

VB.NET (Converted Code)

Dim xEle As XElement = XElement.Load("..\..\Employees.xml")


        xEle.Add(New XElement("Employee", _
             New XElement("EmpId", 5), _
             New XElement("Name", "George"), _
             New XElement("Sex", "Male"), _
             New XElement("Phone", "423-555-4224", _
                 New XAttribute("Type", "Home")), _
                 New XElement("Phone", "424-555-0545", _
                   New XAttribute("Type", "Work")), _
                   New XElement("Address", _
                        New XElement("Street", "Fred Park, East Bay"), _
                        New XElement("City", "Acampo"), _
                        New XElement("State", "CA"), _
                        New XElement("Zip", "95220"), _
                        New XElement("Country", "USA"))))

        xEle.Save("..\..\Employees.xml")
        Console.WriteLine(xEle)

        Console.ReadLine()

Well with that, we conclude this long article of some 'How Do I' operations while using LINQ to XML. Through this
article, we have only attempted to scratch the surface of what can be done using LINQ to XML. LINQ to XML is
an amazing API and I hope this set of examples has demonstrated that. The entire source of the article in C#
and VB.NET can be downloaded over here (Github).

The VB.NET code has been translated using a C# to VB.NET Converting tool.

WHAT OTHERS ARE READING!


Deferred vs Immediate Query Execution in LINQ

Converting a LINQ query to PLINQ

50 LINQ Examples, Tips and How To's

LINQ: Join Between a Collection and XML Data

Longest and Shortest Type Name in .NET 4.0 using LINQ

Querying a Hierarchical Parent-Child Structure in LINQ

Was this article worth reading? Share it with fellow developers too. Thanks!

Share on Facebook Share on Twitter Share on LinkedIn Share on Google+

AUTHOR

Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC
Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of
books 51 Recipes using jQuery with ASP.NET Controls and a new one recently at The
Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for nine times in a row now. In a
professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that
represents premium web sites and digital publications comprising of Professional web,
windows, mobile and cloud developers, technical managers, and architects.

Get in touch with him on Twitter @suprotimagarwal, LinkedIn or befriend him on Facebook

FEEDBACK - LEAVE US SOME ADULATION, CRITICISM AND EVERYTHING IN BETWEEN!

Click here to post your Comments Old Comments (Read Only)

FEATURED TOOLS
CATEGORIES

 .NET Web

 .NET Framework, Visual Studio and C#

 Patterns & Practices

 Cloud and Mobile

 JavaScript

 .NET Desktop

 Interview Questions & Product Reviews

JOIN OUR COMMUNITY

  
51,059 7,564 102,312
fans followers subscribers

POPULAR ARTICLES

C# 8.0 – New Planned Features

Writing Honest Methods in C#

C# 7.1, 7.2 and 7.3 - New Features (Updated)

Dynamic Binding in C#

.NET Core Application Development in Visual Studio Code (VS Code)

C# Sharding and Multithreading - Deep Dive


Getting Started with HTTP Client in Angular (GET, POST, PUT, DELETE methods)

Aspect Oriented Programming in C# via Functions

Angular Evolution - Version 1.x to 6

TypeScript – A Tour of Generics

Interview with the C# Boss - Mads Torgersen

Building a Speech To Text Artificial Intelligence app in C# and Azure

Xamarin.Forms 3 - Cheat sheet

Unit testing with Vue.js (using vue-test-utils, mocha-webpack and the vue-cli)

Load Testing with Azure and Visual Studio Team Services (VSTS)

FREE .NET MAGAZINES


Tags
ASP.NET MVC ASP.NET CORE ASP.NET SHAREPOINT DESIGN PATTERNS C# LINQ WPF WCF

VISUAL STUDIO VSTS & TFS AZURE ENTITY FRAMEWORK ANGULAR.JS REACT.JS JQUERY JAVASCRIPT

HTML5 .NET CORE .NET FRAMEWORK

JQUERY COOKBOOK
SERVER-SIDE CLIENT-SIDE .NET CLOUD AND SKILL UP FOLLOW US
MOBILE

ASP.NET Angular.js C# Design Patterns Facebook


Microsoft Azure
ASP.NET Core React.js Visual Studio Software Twitter
DevOps
ASP.NET MVC jQuery VSTS & TFS Gardening Github
Xamarin
WCF Backbone.js LINQ .NET Interview
Powershell
SharePoint HTML5 Entity Q&A
Machine
CSS Framework Magazines
Learning & AI
.NET Books
UWP &
Framework Product
Windows Store
.NET Standard Reviews
Windows Phone
& .NET Core

WPF

WinForms

© 2007-2018 DotNetCurry.com (A subsidiary of A2Z Knowledge Contact Us Write For Us Privacy


Visuals Pvt. Ltd). All rights reserved.
JavaScript Cookbook Home Submit About Search

Traversing DOM (sub)trees with a recursive "walk the DOM" function.


This function traverses a DOM (sub)tree and executes a given function on each Element and Text node it visits.

function walkTheDOM(node, func) {


func(node);
node = node.firstChild;
while (node) {
walkTheDOM(node, func);
node = node.nextSibling;
}
}

// Example usage: Process all Text nodes on the page


walkTheDOM(document.body, function (node) {
if (node.nodeType === 3) { // Is it a Text node?
var text = node.data.trim();
if (text.length > 0) { // Does it have non white-space text content?
// process text
}
}
});

Author: Douglas Crockford


Source: http://www.youtube.com/watch?v=Y2Y0U-2qJMs&feature=youtu.be&t=27m15s
Tags: dom

comments powered by Disqus


Search…
Home

PUBLIC

Clicking specific Co-Ordinates of a site using GetElementFromPoint


Stack Overflow

Ask Question
Tags

Users

Jobs
0
Log In Sign Up

Teams Q&A for work


Learn More

I'm trying to automate a click process using vb.net and logging into a specific site.

My current issue is that the input fields and login button do not have id's nor a class and because I can't find a
working way of modifying their values or invoking a click I'm taking the brute route of using co-ordinates and
invoking a click on the co-ordinates.

Dim NewPoint As New Point(71, 386)


Dim ele As HtmlElement = Form2.WebBrowser1.Document.GetElementFromPoint(NewPoint)
ele.InvokeMember("click")

I have gotten those specific co-ordinates using a timer and a calculation to calculate the true x and y of the
site

lbl_mousex.Text = "Mouse Position X:" & MousePosition.X - Form2.WebBrowser1.Location.X - 8


lbl_mousey.Text = "Mouse Position y:" & MousePosition.Y - Form2.WebBrowser1.Location.Y - 29

But even after this it's not invoking the click at all.

I'm slowly running out of ideas and I can't figure out why it's not working.

vb.net webbrowser-control

share improve this question

asked May 27 '14 at 12:51


Join Stack Overflow to learn, share knowledge, and build your career.

Crystalwolf
Email Sign Up
OR 32
SIGN10
IN WITH

add a comment
Google

Facebook
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service.
1 Answer active oldest votes

See Webbrowser Click Button With No ID Or Name.

For Each Element As HtmlElement In WebBrowser1.Document.GetElementsByTagName("input")


' You can check name, type or whatever you want
If Element.GetAttribute("name") = "submit" Then
Element.InvokeMember("click")
End If
Next

share improve this answer


edited May 23 '17 at 12:29

Community ♦
1 1

answered May 27 '14 at 13:50

Francesco Menzani
3,870 10 29 64

It doesn't have a class nor does it have any inner text. I'm trying to edit the code to how I would need it but to no avail. The
HTML is so <input type="image" name="submit" src="view/imagesSite/login.gif"> – Crystalwolf May 28 '14
at 8:16

Be creative. I edited my answer. – Francesco Menzani May 28 '14 at 12:44

It appears to be a site specific problem as I've used that on another site and it worked fine. However the site I originally want
to use this on does not do anything with that code. Also I fixed my problem by analysing the post data that is sent out when I
click the login button of the form and it was in plain test so I could easily manipulate the string to login with. – Crystalwolf
May 28 '14 at 13:15

add a comment

Your Answer

Post Your Answer


Post

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie
policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged vb.net webbrowser-control or ask
your own question.

asked 4 years, 4 months ago

viewed 1,248 times

active 3 years, 9 months ago

Linked

1
Webbrowser Click Button With No ID Or Name
Related

0
VB.Net automate flash in WebBrowser

VB WebBrowser control auto click button on


website

VB.NET How to click Ok in msgbox on webbrowser-


control?

0
Clicking a button on a website within VB code

how to disable mouse/mouse clicks inside a web


Browser control?

0
Invoking a click on a specific div

0
WebBrowser, right click on links to open new tab

C# WebBrowser DocumentCompleted event not


firing with specific site

0
Click on web browser

0
VB.NET webbrowser click button

Hot Network Questions


Anxiety attack at work, caused by colleague, how
to handle?

How to install Unity desktop on 18.10?

How to describe two knights defending each


other?

How do variables in C++ store their type?

How should I discuss about a paper with my


potential supervisor who is one of the authors of
that paper?

more hot questions

question feed

STACK OVERFLOW

Questions
Jobs
Developer Jobs Directory
Salary Calculator
Help
Mobile

PRODUCTS

Teams
Talent
Engagement
Enterprise

COMPANY

About
Press
Work Here
Legal
Privacy Policy
Contact Us

STACK EXCHANGE
NETWORK

Technology
Life / Arts
Culture / Recreation
Science
Other

Blog
Facebook

Twitter
LinkedIn
site design / logo © 2018 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required. rev 2018.10.19.31939
File Formats
 / File Formats / PDF / Working with HyperLinks

Custom Search
 PDF

Contents '
Support Forum Download
1. Working with Web navigation
2. Working with internal document navigation
3. Working with external document navigation

Working with Hyperlinks


In PDF, hyperlinks can be added to allow the users to navigate to another part of PDF file, web page or any other external
content. Essential PDF provides support for all these types of hyperlink.

Working with Web navigation


You can navigate to specified URL from a PDF document by using the PdfTextWebLink class.

Please refer the below code snippet for navigating to the web page.

c# vb.net uwp asp.net core xamarin

To add a web hyperlink to an existing document, please refer the below code snippet.

c# vb.net uwp asp.net core xamarin

Working with internal document navigation


To allow the users to navigate to any other part of the same document, PdfDocumentLinkAnnotation class can be used. The
below code explains how to add the hyperlink for internal document navigation.

c# vb.net uwp asp.net core xamarin

To add a PdfDocumentLinkAnnotation to an existing document, please use the below code snippet.

c# vb.net uwp asp.net core xamarin

Working with external document navigation


You can open external documents like images, text files, PDF, etc. using PdfFileLinkAnnotation class.

Please refer the below code snippet for navigating to external documents:

c# vb.net uwp asp.net core xamarin

NOTE
The above link makes use of the absolute path of the file for navigation. So, moving the files
to another machine or location may lead to file not found error in PDF reader applications.

To open a file in relative path, the PdfLaunchAction can be used. While using the relative path in launch action, the files can be
moved to any machine, provided the relative path is being maintained. The below code snippet explains the same.

c# vb.net uwp asp.net core xamarin

Was this page helpful? Yes No


Thank you for your feedback!
Thank you for your feedback and comments. We will rectify this as soon as possible!
An unknown error has occurred. Please try again.
Help us improve this page
Correct inaccurate or outdated content
Please provide additional information
Improve illustrations or images
Please provide additional information
Fix typos or broken links
Please provide additional information
Add more information
Please provide additional information
Correct inaccurate or outdated code samples
Please provide additional information
Other
Please provide additional information

Email (optional)

I agree to the creation of a Syncfusion account in my name and to be contacted regarding this message. No further
action will be taken. Please see our Privacy Policy.

Cancel Submit

Copyright © 2001 - Syncfusion Inc. All Rights Reserved


You might also like