XSLT在以后的子节点中使用第一个子节点值

时间:2016-10-16 07:42:28

标签: html xml xslt transform

我有一个HTML文件,使用XSLT转换为XML文件,我只需要抓取第一个子节点的日期值,以便在后面的子节点中使用,因为后面的子节点没有数据值,标签将显示为空。我尝试使用定位来为XSLT做这件事,但无济于事。

相关的HTML代码是:

<tbody>
  <tr>
    <th rowspan="8" scope="rowgroup">2005DEC</th>  
    <th scope="row">Blemish on Card</th>

  </tr>

  <tr>
    <th scope="row">Damaged</th>

  </tr>

  <tr>
    <th rowspan="8" scope="rowgroup">2006JAN</th>  
    <th scope="row">Lost</th>

  </tr>

  <tr>
    <th scope="row">Stolen</th>

  </tr>
</tbody>

相关的XSLT代码是:

<xsl:for-each select="html/body/div/div/div/table/tbody/tr">
    <Entry>
        <xsl:choose>
            <xsl:when test="th[@scope='rowgroup']">
                <Year>
                    <xsl:value-of select="substring(th[@scope='rowgroup']/., 1, 4)" />
                </Year>
                <Month>
                    <xsl:value-of select="substring(th[@scope='rowgroup']/., 5, 3)" />
                </Month>
            </xsl:when>
            <xsl:otherwise>
                <Year>
                    <xsl:value-of select="substring(tr[1]/th[@scope='rowgroup']/., 1, 4)" />
                </Year>
                <Month>
                    <xsl:value-of select="substring(tr[1]/th[@scope='rowgroup']/., 5, 3)" />
                </Month>
            </xsl:otherwise>
        </xsl:choose>
    </Entry>
</xsl:for-each>

输出的XML代码如下所示,这不是我想要的,因为第二个子节点没有第一个子节点的日期值,只显示为年和月的空值标记: / p>

<Entry>
  <Year>2005</Year>
  <Month>DEC</Month>
  <Reason>Blemish on Card</Reason>
</Entry>
<Entry>
  <Year/>
  <Month/>
  <Reason>Damaged</Reason>
</Entry>
<Entry>
  <Year>2006</Year>
  <Month>JAN</Month>
  <Reason>Lost</Reason>
</Entry>
<Entry>
  <Year/>
  <Month/>
  <Reason>Stolen</Reason>
</Entry>

我需要的是:

<Entry>
  <Year>2005</Year>
  <Month>DEC</Month>
  <Reason>Blemish on Card</Reason>
</Entry>
<Entry>
  <Year>2005</Year>
  <Month>DEC</Month>
  <Reason>Damaged</Reason>
</Entry>
<Entry>
  <Year>2006</Year>
  <Month>JAN</Month>
  <Reason>Lost</Reason>
</Entry>
<Entry>
  <Year>2006</Year>
  <Month>JAN</Month>
  <Reason>Stolen</Reason>
</Entry>

我如何为我的XSLT做到这一点?

1 个答案:

答案 0 :(得分:1)

如果要从第一行中选择数据,则必须先向上导航:substring(../tr[1]/th[@scope='rowgroup']/., 1, 4)

根据您的评论不是您想要的,如果您想要使用scope="rowgroup"属性从第一个前一个兄弟行中选择数据,那么单向继续您的方法

<xsl:for-each select="//tbody/tr">
    <Entry>
        <xsl:choose>
            <xsl:when test="th[@scope='rowgroup']">
                <Year>
                    <xsl:value-of select="substring(th[@scope='rowgroup']/., 1, 4)" />
                </Year>
                <Month>
                    <xsl:value-of select="substring(th[@scope='rowgroup']/., 5, 3)" />
                </Month>
            </xsl:when>
            <xsl:otherwise>
                <Year>
                    <xsl:value-of select="substring(preceding-sibling::tr[th[@scope='rowgroup']][1]/th[@scope='rowgroup'], 1, 4)" />
                </Year>
                <Month>
                    <xsl:value-of select="substring(preceding-sibling::tr[th[@scope='rowgroup']][1]/th[@scope='rowgroup'], 5, 3)" />
                </Month>
            </xsl:otherwise>
        </xsl:choose>

        <xsl:for-each select="th[@scope='row']">
            <Reason>
                <xsl:value-of select="." />
            </Reason>
        </xsl:for-each>
    </Entry>
</xsl:for-each>

如果使用XSLT 2.0处理器,我可能更容易使用for-each-group group-starting-with="tr[th[@scope = 'rowgroup']]"