Feb 6, 2006

Styling Office XML Documents

This post has been due for several days now. Been doing more research into Office 2003's XML file formats. The primary port of call for all budding Office 2003 XML developers is Office 2003 XML Reference Schemas. This is where you can download the schemas -- the formal descriptions -- and the explanatory documentation on the XML document formats for Word, Excel and others. Another important link is to the page for O'Reilly's new book, Office 2003 XML. There is a download for a sample chapter, Chapter 2: The WordprocessingML Vocabulary. Obviously these are very important references for someone who is just entering the field.

When I posted my last entry, I had already created the style file that tells Word how to display the raw account listing. I just wanted to play around with it a little bit, especially to see if I could get the table formatting right. The formatting as it currently is, is OK; but I wanted to customise it a little bit.

By now I've realised that mastery of tables in WordprocessingML will take some time and (at least) a couple of good references (see links above). So I'll just go ahead with the original plan.

Before I list the actual XSL transformations file that does the magic, I want to actually show its results, to get some oohs and aahs from the audience. Here they are:



The account listing as shown by Word when Word has no way of knowing how else to show it.


alist



The account listing with an XSL transformation applied by Word. That is, when the XSL file tells Word how to display it.


alist_transformed



OK, here is the XSL style file:


<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:al="http://yawar.blogspot.com">
<xsl:template match="/">
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve">
<o:DocumentProperties>
<o:Title>Account Listing</o:Title>
<o:Author>Yawar Amin</o:Author>
</o:DocumentProperties>
<w:fonts>
<w:defaultFonts w:ascii="Times New Roman" w:h-ansi="Times New Roman" w:cs="Times New Roman"/>
</w:fonts>
<w:styles>
<w:style w:type="paragraph" w:default="on" w:styleId="Normal">
<w:name w:val="Normal"/>
<w:rPr>
<wx:font wx:val="Times New Roman"/>
<w:sz w:val="24"/>
<w:sz-cs w:val="24"/>
<w:lang w:val="EN-GB" w:fareast="EN-US" w:bidi="AR-SA"/>
</w:rPr>
</w:style>
<w:style w:type="paragraph" w:styleId="Heading1">
<w:name w:val="heading 1"/>
<wx:uiName wx:val="Heading 1"/>
<w:basedOn w:val="Normal"/>
<w:next w:val="Normal"/>
<w:rsid w:val="00B04D4D"/>
<w:pPr>
<w:pStyle w:val="Heading1"/>
<w:keepNext/>
<w:pBdr>
<w:top w:val="dotted" w:sz="4" wx:bdrwidth="10" w:space="1" w:color="auto"/>
</w:pBdr>
<w:spacing w:before="240" w:after="60"/>
<w:jc w:val="center"/>
<w:outlineLvl w:val="0"/>
</w:pPr>
<w:rPr>
<wx:font wx:val="Times New Roman"/>
<w:b/>
<w:b-cs/>
<w:kern w:val="32"/>
<w:sz w:val="48"/><w:sz-cs w:val="48"/>
</w:rPr>
</w:style>
<w:style w:type="table" w:styleId="MyTableContemporary">
<w:name w:val="My Table Contemporary"/>
<w:basedOn w:val="TableNormal"/>
<w:rPr>
<wx:font wx:val="Times New Roman"/>
</w:rPr>
<w:tblPr>
<w:tblInd w:w="0" w:type="dxa"/>
<w:tblBorders>
<w:insideH w:val="single" w:sz="18" wx:bdrwidth="45" w:space="0" w:color="FFFFFF"/>
<w:insideV w:val="single" w:sz="18" wx:bdrwidth="45" w:space="0" w:color="FFFFFF"/>
</w:tblBorders>
<w:tblCellMar>
<w:top w:w="0" w:type="dxa"/>
<w:left w:w="108" w:type="dxa"/>
<w:bottom w:w="0" w:type="dxa"/>
<w:right w:w="108" w:type="dxa"/>
</w:tblCellMar>
</w:tblPr>
<w:tblStylePr w:type="firstRow">
<w:rPr>
<w:b/>
<w:b-cs/>
<w:color w:val="auto"/>
</w:rPr>
<w:tblPr/>
<w:tcPr>
<w:tcBorders>
<w:tl2br w:val="none" w:sz="0" wx:bdrwidth="0" w:space="0" w:color="auto"/>
<w:tr2bl w:val="none" w:sz="0" wx:bdrwidth="0" w:space="0" w:color="auto"/>
</w:tcBorders>
<w:shd w:val="pct-20" w:color="000000" w:fill="FFFFFF" wx:bgcolor="F2F2F2"/>
</w:tcPr>
</w:tblStylePr>
<w:tblStylePr w:type="band1Horz">
<w:rPr>
<w:color w:val="auto"/>
</w:rPr>
<w:tblPr/>
<w:tcPr>
<w:tcBorders>
<w:tl2br w:val="none" w:sz="0" wx:bdrwidth="0" w:space="0" w:color="auto"/>
<w:tr2bl w:val="none" w:sz="0" wx:bdrwidth="0" w:space="0" w:color="auto"/>
</w:tcBorders>
<w:shd w:val="pct-5" w:color="000000" w:fill="FFFFFF" wx:bgcolor="FFFFFF"/>
</w:tcPr>
</w:tblStylePr>
<w:tblStylePr w:type="band2Horz">
<w:rPr>
<w:color w:val="auto"/>
</w:rPr>
<w:tblPr/>
<w:tcPr>
<w:tcBorders>
<w:tl2br w:val="none" w:sz="0" wx:bdrwidth="0" w:space="0" w:color="auto"/>
<w:tr2bl w:val="none" w:sz="0" wx:bdrwidth="0" w:space="0" w:color="auto"/>
</w:tcBorders>
<w:shd w:val="pct-20" w:color="000000" w:fill="FFFFFF" wx:bgcolor="F2F2F2"/>
</w:tcPr>
</w:tblStylePr>
</w:style>
</w:styles>
<w:docPr>
<w:view w:val="print"/>
<w:zoom w:percent="100"/>
<w:doNotEmbedSystemFonts/>
<w:validateAgainstSchema/>
<w:saveInvalidXML w:val="off"/>
<w:ignoreMixedContent w:val="off"/>
<w:alwaysShowPlaceholderText w:val="off"/>
</w:docPr>
<w:body>
<wx:sect>
<w:sectPr>
<w:pgSz w:w="11909" w:h="16834" w:orient="portrait" w:code="9"/>
</w:sectPr>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t>ACCOUNT LISTING</w:t>
</w:r>
</w:p>
<w:p></w:p>
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="MyTableContemporary"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblLook w:val="01E0"/>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="2832"/>
<w:gridCol w:w="3238"/>
<w:gridCol w:w="2089"/>
<w:gridCol w:w="3061"/>
</w:tblGrid>
<w:tr>
<w:tc>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t>Account ID</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>Holder Name</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t>Balance</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>Debit/Credit</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<xsl:for-each select="al:accountlist/al:account">
<xsl:sort select="al:holdername"/>
<w:tr>
<w:tc>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t><xsl:value-of select="al:accid"/></w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t><xsl:value-of select="al:holdername"/></w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t><xsl:value-of select="al:balance"/></w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t><xsl:value-of select="al:drcr"/></w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</xsl:for-each>
</w:tbl>
</wx:sect>
</w:body>
</w:wordDocument>
</xsl:template>
</xsl:stylesheet>


Yeah, whew! That was intense. Mostly though, it was the Word XML markup, which I won't even try to explain now. But for more on WordprocessingML, please check out the latest article at Brian Jones' blog. It's got an excellent mid-level overview.

I've made the XSL instructions bold so you can pick them out clearly and marvel at how few of them there are. (By the way, learned the XSLT at the W3Schools' XSLT Tutorial.) Basically, they say the same thing I described towards the end of my last entry.

Sorry about the underlines in the listing -- have been exploring off-the-top-of-my-head ways to best show listings in HTML, and this is the best compromise I've been able to find between source code editability and web page readability. Will update later if I find anything better. Leave comments with any ideas you might have. Well, got rid of the underlines with some cool new hacks I didn't know about before. Check out the rule for the <pre> tag in my stylesheet.


So what has this exercise accomplished? We see that Word has become, as a result of customers' demands on it, a full-fledged XML transformation and validation engine. With this power, businesses have an amazing new ability to juggle information around, push it into and pull it out of Office documents, change it, and just generally go crazy with it.

I know that the trend in business lately forever in our age has been to, whenever a new problem is faced, just throw more technology at it. Am I complaining? No way. Bring it on!

No comments: