0

我是 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 属性跳过的空行值。

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

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

一些帮助将不胜感激

4

2 回答 2

1

step1:您需要声明输出格式,即“text”而不是“xml”..

step2:你需要去掉额外的空格。使用带有 element='*' 的 Strip-space,这意味着 'all'!

step3:你需要先写标题行,即col1,col2等。
所以使用模板匹配选择一个元素行,它在你的XML中是第一个。假设所有行都有相同的列数,你需要写“COL+ NUMBER" ..column numbers = no of cells你在第一行。

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

step5:调用泛型函数

step6:解释通用函数:该函数复制每个单元格下的数据,以\. 只有第一行,我们会手动调用它,否则模板匹配会处理它。

这是代码:

<?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
于 2012-11-28T12:22:04.447 回答
1

这很棘手,因为正如您所看到的,Excel 会跳过没有出现数据的列,然后为后续的非空白列提供 ss:Index 属性。您必须自己重建“丢失”的单元格位置。也就是说,如果您希望在示例中保留原始列位置,如“15”或“131”,中间有空格。

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

<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()。然而,递归模板可能适用于更复杂的输出。

于 2012-11-28T13:32:47.787 回答