XSLT转换(帮助)

时间:2012-11-28 10:31:28

标签: xslt

我刚接触XSLT并且遇到一些麻烦来解决这个问题。

输入来自XML Excel文档,格式为:

<Row>
  <Cell><Data ss:Type="String">ToE.3</Data></Cell>
  <Cell ss:Index="15"><Data ss:Type="String">Maintain</Data></Cell>
  <Cell><Data ss:Type="Number">3</Data></Cell>
  <Cell><Data ss:Type="String">Other</Data></Cell>
  <Cell ss:Index="131"><Data ss:Type="String">Windows 2003</Data></Cell>
  <Cell><Data >Microsoft SQL Server 2005</Data></Cell>
</Row>
..more rows (note the excel sheet has 132 columns)

我需要将其转换为标准文本文件,例如(使用右列)分隔符:

Col1  Col2 Col3 ..To.. Col15    Col16 ..To.. Col131
ToE.3                 Maintain 3              Windows 2003

问题是如何使用Index属性插入skipt的空行值。

没有空的索引处理的转换如下:

<xsl:for-each select="Row">
    <xsl:for-each select="Cell/Data">
        <xsl:value-of select="current()"/>
        <xsl:text>\</xsl:text>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
</xsl:for-each>

一些帮助将受到热烈赞赏

2 个答案:

答案 0 :(得分:1)

第1步:你需要声明输出格式,即“text”而不是“xml”..

第二步:你需要摆脱额外的空白。使用带有element ='*'的Strip-space,这意味着'all'!

第3步:你需要首先写标题行,即col1,col2等。
因此,使用模板匹配选择XML中第一个元素行。假设所有行具有相同的列数,则需要在第一行中写入“COL + NUMBER”.. column numbers = no of cells

步骤4:如果单元格是最后一个,则插入'输入字符'..

步骤5:调用泛型函数

步骤6:解释通用功能: 此函数复制由\分隔的每个单元格下的数据。仅对于第一行,我们将手动调用它,否则模板匹配将处理它。

以下是代码:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:template name="Header" match="Row[not(preceding-sibling::Row)]">
    <xsl:for-each select="Cell">
      <xsl:value-of select="'Col'"/>
      <xsl:value-of select="position()"/>
      <xsl:if test="position()!=last()">
        <xsl:value-of select="'\'"/>
      </xsl:if>
     </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
    <xsl:call-template name="CopyData"/>
  </xsl:template>

  <xsl:template name="CopyData" match="Row">
    <xsl:for-each select="Cell">
      <xsl:for-each select="Data">
        <xsl:apply-templates select="."/>
      </xsl:for-each>
      <xsl:if test="position()!=last()">
        <xsl:value-of select="'\'"/>
      </xsl:if>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

相应的样本输出:

Col1\Col2\Col3\Col4\Col5\Col6
ToE.3\Maintain\3\Other\Windows 2003\Microsoft SQL Server 2005
ToE.3\Maintain\3\Other\Windows 2003\Microsoft SQL Server 2005

答案 1 :(得分:1)

这很棘手,因为当您看到Excel跳过没有数据出现的列时,会为后续的非空列提供ss:Index属性。你必须自己重建“缺失”的细胞位置。也就是说,如果您希望在示例中保留原始列位置,例如“15”或“131”,则插入空格。

同意上面的InfantProgrammer,但建议您在上面的“CopyData”模板中添加一些逻辑,以(a)确定丢失的单元格的数量,然后(b)调用递归的命名模板将'em'写入输出。

<xsl:template name="WriteBlanks">
   <xsl:param name="Count" select="0"/>
   <xsl:if test="Count &gt; 0">
     <xsl:value-of select="'\'"/>
      <xsl:call-template name="WriteBlanks">
         <xsl:with-param name="Count" select="$Count - 1"/>
      </xsl:call-template>
   </xsl:if>
</xsl:template>

您可以执行类似的操作来生成第一行列标题。

考虑到只需将反斜杠字符作为列分隔符编写的简单性,只需创建一长串字符串就可以实现更简洁的方法,然后XPath substring()需要尽可能多地删除。{{1}}可以实现。但是,递归模板可能适用于更复杂的输出。