Count XML items with specific attribute value

To count the number of nodes that have specific attribute or that have attribute with specific value in your XSLT transformation, use the following code:
  • All elements having the specified attribute:
  • <xsl:select value="count(//*[@attr])" />
  • All elements having attribute with desired value:
  • <xsl:select value="count(//*[@attr = 'value'])" />
For example, to count all elements in an XHTML document having a class name, use:
<xsl:select value="count(//*[@class])" />
To count all elements with class name containing 'menu' use:
<xsl:select value="count(//*[contains(@class,'menu')])" />

Line breaks in XSLT-generated text document

If you're generating text documents with XSLT transformation and use xsl:text tags for tight whitespace control, you might need to insert the end-of-line characters into the output stream manually. You could do that with a newline within the xsl:text tag, like this:
<xsl:text>
</xsl:text>
However, using explicit newline character (&#xa; or &#10;) results in more explicit code that's easier to read, understand and maintain:
<xsl:text>&#xa;</xsl:text>

XPATH expressions in MSXML selectNodes() function are evaluated on the whole DOM tree

The selectNodes() function available in the Microsoft XML (MSXML) API evaluates the XPATH expressions supplied as the argument in the context of the whole DOM tree to which the DOM node belongs, not just the node on which the selectNodes function was executed. For example, if you use the following code …
set firstDiv = document.selectSingleNode("//div")
set paraList = firstDiv.selectNodes("//p")
… the paraList will contain the list of all paragraphs in the whole document, not just the list of paragraphs in the DIV on which the selectNodes call was executed.

Tight control on whitespaces in XSLT-generated documents

Continuing from the previous post on the whitespace issues, here are a few rules that you should keep in mind:
  • Whitespace-only text nodes are not copied from the XSLT document into the output document;
  • Text nodes containing non-whitespace characters are copied in their entirety, including any whitespace characters that are copied verbatim. Extra line breaks can easily appear in your output text, more so if you try to apply nice readable format to the source XSLT document.
  • If you want very tight control on the generated output, place the non-whitespace characters only within the xsl:text tags. The contents of the xsl:text tag (which cannot contain any embedded tags) is copied straight into the output document.

The whitespace control is extremely important if you're generating text output with XSLT transformation.

Word to MediaWiki conversion with XSLT

I've tried two Word to MediaWiki converters: the set of macros described in the Word2MediaWikiPlus extension and the OpenOffice converter. The OpenOffice converter does not work too well (for example, if you have a paragraph style with COURIER font, it's not transformed into MediaWiki code markup) and I needed some extensions that would be hard to cram into Word macros used by Word2MediaWikiPlus, so I decided to implement the converter as an XSLT translator (usable in Word 2003/2007) that should be easy(er) to modify for someone fluent in XSLT. You can find the current (pre-alpha) sources on SourceForge and download the alpha release. If I'm missing a functionality you desperately need, let me know.

Soft breaks in WordProcessingML

The WordProcessingML has an “interesting” way of representing soft breaks (Ctrl-Enter in Word): if a range (w:r, also called run) has a w:br child, it represents a soft break at that position (see also Section 2.3.3 of Part 4 of ECMA-376). Here is the XML Notepad display of a sample three-line paragraph (with two soft breaks):To process the soft break in a range with XSLT, use templates similar to these:
<xsl:template match="w:r">
  <xsl:apply-templates />
</xsl:template>

<xsl:template match="w:t"><xsl:value-of select="text()" /></xsl:template>

<xsl:template match="w:br|w:cr"><br /></xsl:template>

Generate ATOM feed in Microsoft SQL Server

Microsoft SQL Server 2005 can generate XML document straight from the relational tables. If you want to publish an ATOM feed based on data stored in your database, you no longer have to write complex server-side scripts; the SQL server can do all the work for you. I've described the step-by-step solution complete with code samples and printouts in an article “Generating Atom Feed from SQL Data” that was recently published by InformIT.

Implementing Access Controls on SQL Server Data

Most relational databases provide fine-tuned access controls to various objects in the database, including tables, views, and indices, but lack the support for individual row (record) access control. In the “Implementing Access Controls on SQL Server Data” article I wrote for InformIT, I'm describing how you can implement record-level access control in any relational database that supports triggers and separate access controls for views and underlying tables.

Analyze your web page peformance

Straight from the Yahoo Developer Network: YSlow analyzes any web page and generates a grade for each rule and an overall grade. If a page can be improved, YSlow lists the specific changes to be made. Highly recommended tool :)

Back to the future?

In his blog post, Steve Souders describes how IE8 increases the page download performance by using more than two parallel HTTP sessions, briefly mentioning that this violates the recommendation from RFC 2616, which was, after all, written in 1999.

Some web developers might be too young to remember why RFC 2616 has the "two parallel sessions" recommendations. It was (among other reasons) a result of the disasters an earlier version of Internet Explorer (IE3?) caused on the Web infrastructure when Microsoft in its infinite wisdom decided to open multiple parallel HTTP sessions. The browsers quickly overloaded WAN links, caused server overloads (if you use 6 parallel sessions instead of two, all of a sudden the number of "visitors" increases three-fold), firewall failures (some firewalls had licenses limiting the number of parallel sessions) and potentially NAT failures (if you have to do port-address-translation, you might run out of port numbers).

But it looks like the history needs to repeat itself ... or maybe this time the infrastructure is ready for the additional load? My "what could fail" bet would be on the servers, but we'll see in a few months ...

Reliability of client-side XSLT transformations

I've received an interesting question on my “Search Engine Optimization in XML+XSLT designs” post:
Are there considerable browser-specific differences in xsl transformation, or am I being overly cautious?
I've been using browser-side XSLT processing for three years. Although I had initial share of problems with IE5 and some releases of IE6 (finally forcing me to perform server-side transformations for IE5), IE6/7 and Firefox behave almost identically as long as your XSLT is valid. Firefox is a bit more relaxed in error handling, so it might survive an invalid stylesheet and ignore the error. Handling XML/XSLT errors on IE is a nightmare: if the XSLT transformation fails, it's almost impossible to reload the document without closing the browser (obviously IE has some serious caching problems with XML documents). To test new XSLT transformations, I usually force server-side transformations and receive good error messages from server's MSXML.

Opera is a different story. It didn't support XSLT until pretty recently and even then the document() function was broken. I have simply decided not to offer XML data to Opera visitors (they are a minority anyway) and Safari is not widespread enough in my customer base to notice.

This post is part of You've asked for it series of articles.

Four very useful XSLT tricks

Attribute value template, Muenchian Grouping, Usage of XPath axes, handling input XML namespaces. Highly recommended reading :)

Web 2.0 is not necessarily a good thing

A sane voice in the Web-2.0-crazy world: Jacob Nielsen analyzes the impact of AJAX on web usability (beyond the cool factor) and its impact on the bottom line.

Set output attributes with XSLT

Setting attributes in output elements generated by XSLT transform is extremely easy: just enclose the XPath expression in curly brackets within the quotes surrounding the attribute value. You might even concatenate multiple XPath expressions or XPath expressions and string constants within the attribute value. For example, if you want to set CLASS attribute of the output DIV element to the value of the input @id attribute prefixed by "CSS-", use the following syntax:
<DIV class="CSS-{@id}">
However, if you want to eliminate the attributes that would have empty values (for example, the DIV element in the previous example should not have the class attribute if the @id input attribute does not exist), use xsl:attribute in combination with xsl:if or xsl:choose.

Microsoft's XMLHttpRequest Objects

If you don't want to use a wrapper library like Sarissa and plan to work out the differences between Microsoft's and other vendors' implementation of XMLHttpRequest, you'll find a lot of details in this post by Jonathan Snook.