Merge HTML Template with XML Data Source

I was recently working on a project where I needed to create an HTML receipt for a client. Instead of building the HTML on the fly I decided to keep the data and display separate. My goal was to create a mail-merge type of process where XML is referenced in an HTML template. I accomplished this using XSLT. This article explains the steps I performed to complete this process.

I began by adding the details of my receipt into XML using the XmlDocument object. To make this easier I added some helper extensions to my project. These extensions make it easy to add child nodes and attributes:
Next, I created the XML. Here is a sample with some random ids, names, and prices that would normally be fetched from a DataSource:
So what does this output look like? To see for yourself you can set a break-point after the code, and run it. Hover over the xml variable and look at the InnerXml. The above code generates the following XML structure:
Next, I created an XSLT file. I usually place this in the project's bin > Debug folder so it is easily referenced after publishing (nugets typically do this too). If you don't see that directory in your Solution Explorer click on the "Show All Files" icon in the top toolbar of that window. Right-click on the Debug folder > Add > New Item > Data > XSLT File. Give it a name like InvoiceTemplate.xslt then Add.

A new file will be created with some pre-generated code. We will replace the contents xsl:template with our own HTML page:
Let's dissect this a bit. A large portion of this is the HEAD section with some inline CSSS. In the BODY you will notice a reference to:
Since the first node is "order" then it is a reference to it's id attribute. Next, I built a table to show the items. Notice a loop around the TR tags with the following call:
The select attribute targets the items/item nodes using XPATH. For each ITEM in our XML it will generate a new row. Our first column is for row numbers and set using the position() function. It outputs the current loop iteration index starting with 1. For the second column we read the name attribute from ITEM much like we did the order id. In the third column we take it a step further by retrieving the price and also formatting it:
This will convert the price to US currency using a leading dollar sign, thousands separator, and a two digit remainder. After we exit the loop there is a "Total" row. That cell includes the sum() function:
It tallies the prices for all ITEM nodes and formats the resulting number to US currency.

Next, we need to merge the XML and XSLT. I used the following class to return me a string. It reads your XSLT file into an XmlReader and passes it to an XslCompiledTransform object. It then calls that object's Transform method passing in our XML. It returns the modified output as a string.
Finally, I called this class to retrieve the HTML. To see it in action I created the folder C:Testing. The following code will generate and open an HTML file on the fly with the string you provide:
Give it a try. If you don't see anything then it could be due to the parser not liking empty tags. I've had issues with leaving the tag blank, or including empty tags. When everything works you should get something like this:

Screenshot

That’s about it. Take your HTML and create a page or plug it into an SmtpClient request and send it as a richtext email. Download my sample project if desired.

Read More

Alternative to Using Tables for Layout

Most developers are familiar with tables and how they behave. They have relied on them heavily in the past to display data as well as templating and design. But as we learned in my previous post you are no longer encouraged to use them for layouts. You should use CSS instead.

When I first started dabbling with DIV tables I used the CSS float property to mimic cells. But in many situations that method forced me to be overly specific on the heights and widths of my cells. It seemed to be two-times the work. Also vertical alignment and centering was much more difficult.

But luckily CSS3 has a solution for us with the DISPLAY property: table, table-row and table-cell.

In the following example I have some HTML:
And when you include a little CSS:
Above, I am showing how to easily center a table with auto-sized columns and rows based on the content. I’m also vertically and horizontally aligning a cell with ease. Heights and widths were not required. The height that was set was only to demonstrate vertical-alignment.

The CSS display properties work in all major browsers. They became fully functional as of IE9 but can work in IE8 with an additional meta tag. See this post for more information. IE8 was released on March 19, 2009 and IE9 on March 14, 2011.

Remember that it is just as bad to use tables for layout as it is place tabular data into a DIV table. Tables still have a purpose! If you are confused on when to use each then you may find a better understanding in my previous post.

See a DEMO.

Enjoy.

Read More

When and How to Use Tables

If you are web developer then you have probably heard at some point NOT to use tables for layout. This has to do with best practices for website accessibility. But what really are the rules? The WC3 defines the table model as follows:

The HTML table model allows authors to arrange data — text, preformatted text, images, links, forms, form fields, other tables, etc. — into rows and columns of cells.
On the same page it also mentions that you should not use tables for layout:

Tables should not be used purely as a means to layout document content as this may present problems when rendering to non-visual media.

With that being said, it is perfectly fine to use tables for textual data that can be organized into columns and rows. It is also fine if hyperlinks or image-links are included with the data (i.e., email links). Tables can also be used for input as well. Feel free to use textboxes, dropdowns and other form elements if they all tie to a single record of information.

So what about headers? Are they required? They are required if you are adhering to Section 508 standards for web accessibility:

(g) Row and column headers shall be identified for data tables
(h) Markup shall be used to associate data cells and header cells for data tables that have two or more logical levels of row or column headers.

The presence of table headers help eliminate confusion for both visual and non-visual user agents. The "markup" mentioned above can be performed as follows:

Table Header or <th> cells have a scope attribute. It tells the screen reader whether the header is for a column (col) or for a row (row).

Table Data or td cells have a headers attribute. It contains the id(s) of any <th> cells that apply to it, delimited by spaces.

Scope and headers fulfill the same function so you can choose one or the other. While screen readers may correctly guess whether a header is for a column or row based on table layout, clarifying with one of the above methods makes this unambiguous. However, Section 508 demands the markup if multiple headers are involved.

Abbreviations can also assist in markup:
They can be used for clarification, space-saving (for minimalistic user agents), and repetitive rendering (i.e., speech synthesizers may restate the <th> abbreviated value before reading each associated <td> value).

Hopefully this helps clarify some questions and aids in future development.

Read More

Hidden Accessible Fieldsets

It is good to group checkboxes and radio buttons for accessibility purposes.  The fieldset and legend elements allow developers to group related controls and labels.  Grouping elements make it easier for users to understand their purpose.  Screen readers will detect fieldsets and inform the user of their purpose via the legend tag.  Keep in mind that an elaborate interface may not transfer logically to someone using a screen reader.   With CSS you can cater to both worlds.  You can utilize fieldsets but also hide them if they are not visually pleasing.  A hidden fieldset is completely detectable by a screen reader.

Here is a snipplet of CSS that will hide the fieldset and remove the legend indent.
If you want to hide the legend as well then alter the CSS as so:
See a DEMO

Enjoy.

Read More