2013-10-07 28 views
1

我試圖將保存爲XML的Excel電子表格轉換爲實際的XML文檔(刪除所有對格式化的引用並僅獲取我的數據)。第一行是應該是節點名稱的標題,其餘行是數據。 XML將用於Windows窗體應用程序,並且轉換將通過 XslTransform class of the XML namespace完成。在for-each循環中使用位置方法來訪問節點索引/動態節點創建

我無法使用interop來訪問Excel,因爲程序將使用的機器上沒有MS Office。如果任何列包含分隔符,則保存爲CSV並讀取文件將失敗。我不想只寫一個XML文件或硬編碼信息,因爲它需要在電子表格更改時更新。所以我相信動態生成XML是最好的選擇。

爲了簡便起見,我已經去除了大部分從生成的XML文件中的無關信息,只顯示工作表我感興趣的是:

<?xml version="1.0"?> 
<Worksheet Name="AttributionImages"> 
    <Table ExpandedColumnCount="5" ExpandedRowCount="2" FullColumns="1" 
    FullRows="1"> 
    <Column AutoFitWidth="0" Width="73.5"/> 
    <Column AutoFitWidth="0" Width="84"/> 
    <Column AutoFitWidth="0" Width="121.5"/> 
    <Column AutoFitWidth="0" Width="146.25"/> 
    <Column AutoFitWidth="0" Width="124.5"/> 
    <Row> 
    <Cell><Data Type="String">Name</Data></Cell> 
    <Cell><Data Type="String">Source</Data></Cell> 
    <Cell><Data Type="String">PicSet</Data></Cell> 
    <Cell><Data Type="String">License</Data></Cell> 
    <Cell><Data Type="String">Website</Data></Cell> 
    </Row> 
    <Row> 
    <Cell><Data Type="String">Image1</Data></Cell> 
    <Cell StyleID="s21" HRef="http://www.website.com/"><Data Type="String">Artist </Data></Cell> 
    <Cell><Data Type="String">FreeIcons</Data></Cell> 
    <Cell><Data Type="String">Creative Commons Attribution</Data></Cell> 
    <Cell StyleID="s21" HRef="http://www.website.com/"><Data 
Type="String">http://www.website.com</Data></Cell> 
    </Row> 
    </Table> 
</Worksheet> 

我的XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/Worksheet"> 
<xsl:element name="{@Name}"> 
    <xsl:for-each select="Table/Row"> 
     <xsl:if test="(position()) &gt; 1"> 
       <Image> 
       <xsl:for-each select="Cell"> 
         <xsl:element name="{/Worksheet/Table/Row[1]/Cell[position()]/Data}"> 
         <!-- <countNo><xsl:value-of select="position()"/></countNo> --> 
         <xsl:value-of select="Data"/> 
         </xsl:element>  
       </xsl:for-each> 
       </Image> 
     </xsl:if> 

     </xsl:for-each> 
</xsl:element> 
</xsl:template> 
</xsl:stylesheet> 

我以下線索的信用答案可幫助我開發上述XSLT:

預期輸出:

<?xml version="1.0" encoding="utf-8" ?> 
<AttributionImages> 
<Image> 
    <Name>Image1 </Name> 
    <Source>Artist</Source> 
    <PicSet>FreeIcons</PicSet> 
    <License>Creative Commons Attribution</License> 
    <Website>http://www.Website.com</Website> 
    </Image> 
    </AttributionImages> 

實際輸出:

<?xml version="1.0" encoding="utf-8" ?> 
<AttributionImages> 
<Image> 
    <Name>Image1 </Name> 
    <Name>Artist</Name> 
    <Name>FreeIcons</Name> 
    <Name>Creative Commons Attribution</Name> 
    <Name>http://www.Website.com</Name> 
    </Image> 
    </AttributionImages> 

出於某種原因「/表/表/列1 /細胞[position()]/Data「總是等於第一行的第一個單元格(1 = name)。如果我將位置()替換爲數字1-5,它將訪問正確的索引。此外,我已註釋掉的<countNo><xsl:value-of select="position()"/></countNo>將輸出正確的循環計數。我需要指定cell []索引值來訪問第一行中的所有節點?

回答

0

這是因爲當您執行/Worksheet/Table/Row1/Cell[position()]/Data時,對「position()」的調用將與您的xsl:for-each循環處於不同的上下文中,這將是選擇「/ Worksheet/Table/Row1/Cell 「

你需要做的,是存儲位置的變量之前,然後再引用您的XPath表達式:

<xsl:variable name="position" select="position()" /> 
<xsl:element name="{/Worksheet/Table/Row[1]/Cell[$position]/Data}"> 

事實上,它可能會稍微更有效地使用一鍵在這裏查看標題。試試這個XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="header" match="Table/Row[1]/Cell" use="count(preceding-sibling::Cell) + 1"/> 

    <xsl:template match="/Worksheet"> 
     <xsl:element name="{@Name}"> 
     <xsl:for-each select="Table/Row"> 
      <xsl:if test="(position()) &gt; 1"> 
       <Image> 
        <xsl:for-each select="Cell"> 
        <xsl:variable name="position" select="position()"/> 
        <xsl:element name="{key('header', $position)/Data/text()}"> 
         <xsl:value-of select="Data"/> 
        </xsl:element> 
        </xsl:for-each> 
       </Image> 
      </xsl:if> 
     </xsl:for-each> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 
+0

謝謝你,這段代碼完美地適用於我正在嘗試做的事情。我是XSLT新手,並沒有關於關鍵功能的理想。 – Jayden67