XSLT:如何传播先前的值,直到找到新的值

时间:2013-01-04 14:56:57

标签: xml xslt-1.0

我正在寻找1.0 XSLT转换,它将传播非空单元格,直到找到新的单元格。 我的意见:

<table>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value1</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value2</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
</table>

预期产出:

<table>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value1</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value1</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value1</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value2</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value2</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value2</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value2</column_1>
    <column_2></column_2>
</row>
</table>

我曾尝试使用前面的:: row [1] / column_1,但结果只有一个副本。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>
<xsl:template name="replace-value">
    <xsl:param name="value"/>
    <xsl:copy>
        <xsl:value-of select="$value"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="//column_1">
    <xsl:choose>
        <xsl:when test=".=''">
            <xsl:call-template name="replace-value">
                <xsl:with-param name="value" select="preceding::row[1]/column_1/text()"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy>
                <xsl:apply-templates select="node() | @*"/>
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

像:

<table>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value1</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value1</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value2</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1>Value2</column_1>
    <column_2></column_2>
</row>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>
<row>
    <column_1></column_1>
    <column_2></column_2>
</row>

2 个答案:

答案 0 :(得分:0)

你可以在你的else子句中尝试保存你想要以&lt; xsl:variable name =“saved”select =“。”&gt;向下传播的值,然后在行中:

&lt; xsl:with-param name =“value”select =“preceding :: row [1] / column_1 / text()”/&gt;

改为

&lt; xsl:with-param name =“value”select =“$ saved”/&gt;

取决于您可能希望使用唯一变量名称的不同列数。

答案 1 :(得分:0)

你几乎拥有它,但不是这样:

preceding::row[1]/column_1/text()

你需要这个:

preceding::row[column_1 != ''][1]/column_1/text()

可以进一步简化为:

preceding::column_1[. != ''][1]

因为你需要找到一个非空列的最后一行。

另一方面,我看不出有任何理由使用该替换值模板。您的XSLT可以简化为:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output indent="yes"/>
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="column_1">
    <xsl:copy>
      <xsl:choose>
        <xsl:when test=".=''">
          <xsl:value-of select="preceding::column_1[. != ''][1]"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="node() | @*"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>