2010-01-29 35 views
0

我有这个XML文件,我想创建一个XSL文件将其转换为Excel。每行应代表一个标志。这些列将是关键属性,如颜色,编号,描述以及其他徽标的任何其他关键字。使用XSLT创建Excel(SpeadsheetML)输出

<Top> 
    <logo> 
    <field key="id">172-32-1176</field> 
    <field key="color">Blue</field> 
    <field key="description"><p>Short Description</p></field> 
    <field key="startdate">408 496-7223</field> 
    </logo> 
    <logo> 
    <field key="id">111-111-111</field> 
    <field key="color">Red</field> 
    </logo> 
    <!-- ... -->  
</Top> 

XSL文件是这样的:

<xsl:stylesheet 
    version="1.0" 
    xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    xmlns:user="urn:my-scripts" 
    xmlns:o="urn:schemas-microsoft-com:office:office" 
    xmlns:x="urn:schemas-microsoft-com:office:excel" 
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
> 

    <xsl:template match="/"> 
    <Workbook 
     xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
     xmlns:o="urn:schemas-microsoft-com:office:office" 
     xmlns:x="urn:schemas-microsoft-com:office:excel" 
     xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
     xmlns:html="http://www.w3.org/TR/REC-html40" 
    > 
     <xsl:apply-templates/> 
    </Workbook> 
    </xsl:template> 

    <xsl:template match="/*"> 
    <Worksheet> 
     <xsl:attribute name="ss:Name"> 
     <xsl:value-of> select="local-name(/*)"/> 
     </xsl:attribute> 
     <Table x:FullColumns="1" x:FullRows="1"> 
     <Row> 
      <xsl:for-each select="*/*"> 
      <Cell> 
       <Data ss:Type="String"> 
       <xsl:value-of select="@key"/> 
       </Data> 
      </Cell> 
      </xsl:for-each> 
     </Row> 
     <xsl:apply-templates/> 
     </Table> 
    </Worksheet> 
    </xsl:template> 

    <xsl:template match="/*/*"> 
    <Row> 
     <xsl:apply-templates/> 
    </Row> 
    </xsl:template> 

    <xsl:template match="/*/*/*"> 
    <Cell> 
     <Data ss:Type="String"> 
     <xsl:value-of select="."/> 
     </Data> 
    </Cell> 
    <!-- <xsl:apply-templates/> --> 
    </xsl:template> 
</xsl:stylesheet> 

但数据放置不正确的列名和列名以下的重复。如何才能做到这一点? 这些列可以以任何顺序排列,并且在Excel中第二行的列stardate也应该为空。同样的更多。

回答

2

你非常接近。尝试在模板匹配方面更具体 - 当您可以说template match="field"时,不要说template match"/*/*/*"

除此之外,这是你的方法,只是略作修改:

<xsl:stylesheet 
    version="1.0" 
    xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    xmlns:user="urn:my-scripts" 
    xmlns:o="urn:schemas-microsoft-com:office:office" 
    xmlns:x="urn:schemas-microsoft-com:office:excel" 
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
> 
    <xsl:output method="xml" encoding="utf-8" indent="yes" /> 

    <xsl:template match="/"> 
    <Workbook 
     xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
     xmlns:o="urn:schemas-microsoft-com:office:office" 
     xmlns:x="urn:schemas-microsoft-com:office:excel" 
     xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
     xmlns:html="http://www.w3.org/TR/REC-html40" 
    > 
     <xsl:apply-templates select="Top" /> 
    </Workbook> 
    </xsl:template> 

    <xsl:template match="Top"> 
    <Worksheet ss:Name="{local-name()}"> 
     <Table x:FullColumns="1" x:FullRows="1"> 
     <Row> 
      <!-- header row, made from the first logo --> 
      <xsl:apply-templates select="logo[1]/field/@key" /> 
     </Row> 
     <xsl:apply-templates select="logo" /> 
     </Table> 
    </Worksheet> 
    </xsl:template> 

    <!-- a <logo> will turn into a <Row> --> 
    <xsl:template match="logo"> 
    <Row> 
     <xsl:apply-templates select="field" /> 
    </Row> 
    </xsl:template> 

    <!-- convenience: <field> and @key both turn into a <Cell> --> 
    <xsl:template match="field | field/@key"> 
    <Cell> 
     <Data ss:Type="String"> 
     <xsl:value-of select="."/> 
     </Data> 
    </Cell> 
    </xsl:template> 

</xsl:stylesheet> 

你的“重复列名”的问题根源在此表达:

<xsl:for-each select="*/*"> 

在你的背景下,这一选择文档中的任何第三级元素(字面上全部为<logo>s中的所有<field>节点),并使它们中的标题行出现。我用

<xsl:apply-templates select="logo[1]/field/@key" /> 

这使得标题行出只有第一<logo>代替它。

如果需要某个列顺序(文档顺序除外)或不是所有<field>节点与所有<logo> s的顺序相同,则事情会变得更加复杂。告诉我你是否需要这个。

+0

这正是我所面临的问题。字段的顺序不同,并且并非所有字段都在第一个中。所以我需要拥有所有不同的专栏。 – Learner

+0

@Learner:这不是不可能的,但解决方案取决于你是否想要使用某种自然顺序(例如,按键按字母顺序排序)或者你定义的任意顺序。前者较少,后者较为复杂。我可以为两种偏好创建解决方案。 – Tomalak