[Office開發系列] 誰說寫 Open XML文件產生程式一樣要寫落落長的程式碼?不妨玩玩 XSLT 吧。
在前兩篇 Open XML 文章中,我說明了使用程式的方式產生 Office 2007-2010 的 Open XML 文件,並且整合資料庫中的資料。若你有看過那兩篇文章的話,一定會對那個落落長的程式碼印象深刻,是的,若只想要以寫程式方式來處理的話,那麼長的程式碼是無可避免的,但其實我們有很多種作法,不一定只能依賴 coding directly (直接寫碼的方式執行工作),不要忘了,Open XML 也是一個 XML 文件,所有可以用在 XML 上的方法也可以在 Open XML 上如法炮製,而本文使用的是直接轉換的方法,也就是 XSLT (XML stylesheet/transform),利用 XSLT 會比直接寫碼不但快,而且程式也會非常簡潔。
我們一樣以前兩篇所用的範例文件檔來看,透過 OpenXML Productivity Tool,我們可以得到那個表格的 XML 結構:
<w:tbl xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:tblPr>
<w:tblStyle w:val="-1" />
<w:tblW w:w="0" w:type="auto" />
<w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1" />
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="817" />
<w:gridCol w:w="2687" />
<w:gridCol w:w="2274" />
<w:gridCol w:w="851" />
<w:gridCol w:w="1893" />
</w:tblGrid>
<w:tr w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidTr="0055440F">
<w:trPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
</w:trPr>
<w:tc>
<w:tcPr>
<w:cnfStyle w:val="001000000000" w:firstRow="0" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:tcW w:w="817" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Serial</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2687" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Name</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2274" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Unit</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="851" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:proofErr w:type="spellStart" />
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Qty</w:t>
</w:r>
<w:proofErr w:type="spellEnd" />
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1893" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Price</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidTr="0055440F">
<w:trPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
</w:trPr>
<w:tc>
<w:tcPr>
<w:cnfStyle w:val="001000000000" w:firstRow="0" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:tcW w:w="817" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="0055440F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:bookmarkStart w:name="_GoBack" w:colFirst="4" w:colLast="4" w:id="0" />
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>AAA</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2687" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="006C263F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>AAA</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2274" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="006C263F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>AAA</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="851" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="006C263F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>AAA</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1893" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="006C263F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>AAA</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:bookmarkEnd w:id="0" />
</w:tbl>
為什麼我們要用 XSLT 來處理呢?因為 XSLT 基本上所負責的工作就是將來源的 XML 轉換成另一種格式的 XML (或是 HTML),在中大型應用系統,尤其是要求使用產業標準交換格式 (例如 HIPAA, RosettaNet, HL7 等) 的,在網路上傳遞幾乎全是 XML,而且由資料庫輸出的也都是 XML,若是用 XmlDocument 轉換,不但會太慢程式碼又落落長,這時 XSLT 就顯得非常重要,雖然它的指令很不容易寫,但它卻是處理與轉換 XML 格式文件的最好工具。
在本例中,我們會由資料庫中查詢出一個 XML 格式的資料結果:
<Products>
<Product>
<ProductID>1</ProductID>
<ProductName>Chai</ProductName>
<SupplierID>1</SupplierID>
<CategoryID>1</CategoryID>
<QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit>
<UnitPrice>18.0000</UnitPrice>
<UnitsInStock>39</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>10</ReorderLevel>
<Discontinued>0</Discontinued>
</Product>
<Product>
<ProductID>2</ProductID>
<ProductName>Chang</ProductName>
<SupplierID>1</SupplierID>
<CategoryID>1</CategoryID>
<QuantityPerUnit>24 - 12 oz bottles</QuantityPerUnit>
<UnitPrice>19.0000</UnitPrice>
<UnitsInStock>17</UnitsInStock>
<UnitsOnOrder>40</UnitsOnOrder>
<ReorderLevel>25</ReorderLevel>
<Discontinued>0</Discontinued>
</Product>
…
</Products>
依照這樣的結構,我們可以在 Visual Studio 專案中新增一個 DocumentTable.xslt:
並且在 XSLT 檔中加入下列的 XSLT 指令 (XSLT 指令部份我用紅字標示):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<w:tbl xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:tblPr>
<w:tblStyle w:val="-1" />
<w:tblW w:w="0" w:type="auto" />
<w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1" />
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="817" />
<w:gridCol w:w="2687" />
<w:gridCol w:w="2274" />
<w:gridCol w:w="851" />
<w:gridCol w:w="1893" />
</w:tblGrid>
<w:tr w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidTr="0055440F">
<w:trPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
</w:trPr>
<w:tc>
<w:tcPr>
<w:cnfStyle w:val="001000000000" w:firstRow="0" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:tcW w:w="817" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Serial</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2687" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Name</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2274" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Unit</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="851" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:proofErr w:type="spellStart" />
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Qty</w:t>
</w:r>
<w:proofErr w:type="spellEnd" />
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1893" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="0055440F" w:rsidP="0055440F" w:rsidRDefault="0055440F">
<w:pPr>
<w:cnfStyle w:val="100000000000" w:firstRow="1" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="0055440F">
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>Price</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<xsl:for-each select="./Product">
<w:tr w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidTr="0055440F">
<w:trPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
</w:trPr>
<w:tc>
<w:tcPr>
<w:cnfStyle w:val="001000000000" w:firstRow="0" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="0" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:tcW w:w="817" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="0055440F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:bookmarkStart w:name="_GoBack" w:colFirst="4" w:colLast="4" w:id="0" />
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>
<xsl:value-of select="./ProductID"/>
</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2687" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="006C263F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>
<xsl:value-of select="./ProductName"/>
</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2274" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="006C263F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>
<xsl:value-of select="./QuantityPerUnit"/>
</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="851" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="006C263F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>
<xsl:value-of select="./UnitsInStock"/>
</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1893" w:type="dxa" />
</w:tcPr>
<w:p w:rsidRPr="0055440F" w:rsidR="00257DF3" w:rsidP="006C263F" w:rsidRDefault="00257DF3">
<w:pPr>
<w:cnfStyle w:val="000000100000" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:oddVBand="0" w:evenVBand="0" w:oddHBand="1" w:evenHBand="0" w:firstRowFirstColumn="0" w:firstRowLastColumn="0" w:lastRowFirstColumn="0" w:lastRowLastColumn="0" />
<w:rPr>
<w:rFonts w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="Centaur" w:hAnsi="Centaur" />
</w:rPr>
<w:t>
<xsl:value-of select="./UnitPrice"/>
</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</xsl:for-each>
<w:bookmarkEnd w:id="0" />
</w:tbl>
</xsl:template>
</xsl:stylesheet>
XSLT 完成後,我們撰寫下列程式碼:
// 讀取資料庫並轉換成XML
private static string GetProductItemsXML()
{
SqlConnection conn = new SqlConnection("initial catalog=Northwind; integrated security=SSPI");
SqlCommand cmd = new SqlCommand("SELECT * FROM Products FOR XML PATH ('Product'), root ('Products')", conn);
conn.Open();
XmlReader reader = cmd.ExecuteXmlReader();
reader.Read();
string xmlData = reader.ReadOuterXml();
conn.Close();
return xmlData;
}
// 將資料庫讀出的XML使用XSLT轉換成OpenXML的格式。
private static string RenderOpenXMLTable(string XmlData)
{
XmlDocument doc = new XmlDocument();
XslCompiledTransform xslt = new XslCompiledTransform();
doc.LoadXml(XmlData);
xslt.Load("DocumentTable.xslt");
MemoryStream ms = new MemoryStream();
xslt.Transform(doc.DocumentElement, null, ms);
ms.Flush();
ms.Position = 0;
StreamReader reader = new StreamReader(ms);
string result = reader.ReadToEnd();
reader.Close();
XmlDocument docRender = new XmlDocument();
docRender.LoadXml(result);
result = docRender.DocumentElement.OuterXml;
doc = null;
docRender = null;
xslt = null;
return result;
}
然後在 Main 方法中加入下列程式 (改寫自前面的例子):
static void Main(string[] args)
{
FileStream fs = ReadTemplateFile();
WordprocessingDocument doc = WordprocessingDocument.Open(fs, true);
Document document = doc.MainDocumentPart.Document;
var tableXML = RenderOpenXMLTable(GetProductItemsXML());
var table = new Table(tableXML); // 使用生成的Open XML生成Table物件
document.Body.Append(table); // 將table物件加入文件本體。
doc.MainDocumentPart.Document.Save();
doc.Close();
fs.Close();
}
執行結果為:
執行結果與前面的例子完全相同,但是透過 XSLT,程式碼變得相當簡潔,您也可以將它應用在您的程式中。