XSLT - 添加新元素作为父元素

XSLT - add new element as parent element

我有 xml 如下,

        <table>
            <tbody>
                <tr>
                    <th>Test table head col 1</th>
                    <th><span>Test table head col 2</span></th>
                    <th><span>Test table head col 3</span></th>
                </tr>
                <tr>
                    <td>Row 1 Column 1</td>
                    <td>Row 1 Column 2</td>
                    <td>Row 1 Column 3</td></tr>
                <tr>
                    <td>Row 2 Column 1</td>
                    <td>Row 2 Column 2</td>
                    <td>Row 2 Column 3</td>
                </tr>
                <tr>
                    <td>Row 3 Column 1</td>
                    <td>Row 3 Column 2</td>
                    <td>Row 3 Column 4</td>
                </tr>
            </tbody>
        </table>

使用 XSLT 我必须从上面 xml,

获得以下输出
<table>       
                <thead>
                    <row>
                        <entry namest="1">
                            <p type="Table head">Test table head col 1</p>
                        </entry>
                        <entry namest="2">
                            <p type="Table head">Test table head col 2</p>
                        </entry>
                        <entry namest="3">
                            <p type="Table head">Test table head col 3</p>
                        </entry>
                    </row>
                </thead>
                <tbody>
                    <row>
                        <entry namest="1" align="left">
                            <p type="Table text">Row 1 Column 1</p>
                        </entry>
                        <entry namest="2" align="left">
                            <p type="Table text">Row 1 Column 2</p>
                        </entry>
                        <entry namest="3" align="left">
                            <p type="Table text">Row 1 Column 3</p>
                        </entry>
                    </row>
                    <row>
                        <entry namest="1" align="left">
                            <p type="Table text">Row 2 Column 1</p>
                        </entry>
                        <entry namest="2" align="left">
                            <p type="Table text">Row 2 Column 2</p>
                        </entry>
                        <entry namest="3" align="left">
                            <p type="Table text">Row 2 Column 3</p>
                        </entry>
                    </row>
                    <row>
                        <entry namest="1" align="left">
                            <p type="Table text">Row 3 Column 1</p>
                        </entry>
                        <entry namest="2" align="left">
                            <p type="Table text">Row 3 Column 2</p>
                        </entry>
                        <entry namest="3" align="left">
                            <p type="Table text">Row 3 Column 4</p>
                        </entry>
                    </row>
                </tbody>                
        </table>

为了获得我在 xsl 之后编写的输出,

<xsl:template match="tbody/tr[1]">
        <thead>
            <row>
                <xsl:for-each select="th">
                    <entry namest="{position()}">
                        <p type="Table head"><xsl:apply-templates/></p>
                    </entry>
                </xsl:for-each>
            </row>
        </thead>
    </xsl:template>

    <xsl:template match="tbody/tr[not(position()=1)]">
        <tbody>
            <row>
                <xsl:for-each select="td">
                    <entry namest="{position()}" align="left">
                        <p type="Table text"><xsl:apply-templates/></p>
                    </entry>
                </xsl:for-each>
            </row>
        </tbody>
    </xsl:template>

但它会向每个 <tr> 个节点添加 <tbody>。如何修改我的代码以仅添加一个 <tbody> 元素来覆盖从第二个元素到最后一个元素的 <tr> 个元素作为我的预期输出?

这是一种可能的方式:

<xsl:template match="tbody/tr[position()=2]">
    <tbody>
        <xsl:apply-templates/>
    </tbody>
</xsl:template>

<xsl:template match="tbody/tr[position()&gt;1]">
    <row>
        <xsl:for-each select="td">
            <entry namest="{position()}" align="left">
                <p type="Table text"><xsl:apply-templates/></p>
            </entry>
        </xsl:for-each>
    </row>
</xsl:template>

xsltransform.net demo

第一个模板在处理每个第二个 tr 时添加 tbody 父元素,最后一个模板在先前添加的 tbody 中为每个添加 row 元素tr 位置索引大于 1。

一种做法是匹配tbody元素,然后做特定处理,为第一行创建一个thead元素,然后只将剩余的行复制到tbody

试试这个 XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="tbody">
        <thead>
          <xsl:apply-templates select="tr[1]" />
        </thead>
        <tbody>
            <xsl:apply-templates select="tr[position() > 1]" />
        </tbody>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

如果您想应对已经存在 thead 或可能根本没有 tbody 的情况,您可以改为匹配 table 元素。也试试这个 XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="table">
      <table>
        <thead>
          <xsl:apply-templates select="(.//tr)[1]" />
        </thead>
        <tbody>
          <xsl:apply-templates select="(.//tr)[position() > 1]" />
        </tbody>
      </table>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>