[Office開發系列] 誰說寫 Open XML文件產生程式一樣要寫落落長的程式碼?不妨玩玩 XSLT 吧。

[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:

image

並且在 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();
}

執行結果為:

image

 

執行結果與前面的例子完全相同,但是透過 XSLT,程式碼變得相當簡潔,您也可以將它應用在您的程式中。