类似于这个问题(有更多的相关条目,但是作为一个新的用户I只能发布一个URL): Xpath的获取是

2个元件之间的元件

我有关于组“其他/限定”分子之间发生的元件的选择的问题。试图改变一个平坦的HTML表格时,会发生这种情况 使用XSLT一个分级的XML结构。我试图在模板中使用递归,但撒克逊人拒绝接受这个,因为它导致死锁,最有可能是我的错,但让我们从头开始。

首先源数据是HTML表格:

<table >
    <thead>
        <tr>
            <th>Column 1</th>
            <th>Column 2</th>
            <th>Column 3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th colspan="3" >Group 1</th>
        </tr>
        <tr>
            <td>attribute 1.1.1</td>
            <td>attribute 1.1.3</td>
            <td>attribute 1.1.2</td>
        </tr>
        <tr>
            <td>attribute 1.2.1</td>
            <td>attribute 1.2.2</td>
            <td>attribute 1.2.3</td>
        </tr>
        <tr>
            <td>attribute 1.3.1</td>
            <td>attribute 1.3.2</td>
            <td>attribute 1.3.3</td>
        </tr>
        <tr>
            <th colspan="3" >Group 2</th>
        </tr>
        <tr>
            <td>attribute 2.1.1</td>
            <td>attribute 2.1.3</td>
            <td>attribute 2.1.2</td>
        </tr>
        <tr>
            <td>attribute 2.2.1</td>
            <td>attribute 2.2.2</td>
            <td>attribute 2.2.3</td>
        </tr>
        <tr>
            <td>attribute 2.3.1</td>
            <td>attribute 2.3.2</td>
            <td>attribute 2.3.3</td>
        </tr>
    </tbody>
</table>

在XML的靶向输出将是:

 <groups>
    <group name="Group 1">
        <item attribute1="attribute 1.1.1" attribute2="attribute 1.1.3" attribute3="attribute 1.1.2"/>
        <item attribute1="attribute 1.2.1" attribute2="attribute 1.2.2" attribute3="attribute 1.2.3"/>
        <item attribute1="attribute 1.3.1" attribute2="attribute 1.3.2" attribute3="attribute 1.3.3"/>
    </group>
    <group name="Group 2">
        <item attribute1="attribute 2.1.1" attribute2="attribute 2.1.3" attribute3="attribute 2.1.2"/>
        <item attribute1="attribute 2.2.1" attribute2="attribute 2.2.2" attribute3="attribute 2.2.3"/>
        <item attribute1="attribute 2.3.1" attribute2="attribute 2.3.2" attribute3="attribute 2.3.3"/>
    </group>
</groups>

因此,我希望有所有的项目条目,(TR元素),并将其添加到组中。这基本上可以归结为选择以下所有同胞TR元素,直到我们遇到一个具有TH元素作为孩子。如果我只能确定有TH孩子,表示为一组一个新的标题这个第一TR的位置,这可能是与完成:

<xsl:for-each select="tbody/tr">
    <xsl:if test="th">
        <xsl:element name="group">
            <xsl:attribute name="name"><xsl:value-of select="th"/></xsl:attribute>
            <xsl:for-each select="following-sibling::tr[position() < $positionOfNextThElement]">            
                <xsl:call-template name="item"/>
            </xsl:for-each>
        </xsl:element>
    </xsl:if>
</xsl:for-each>

然而,我无法确定第一个遇到的TR / TH标签的位置。

如前所述我试着在模板递归工作:随时拨打“项目”模板,在此模板决定我们是否要调用它的下一个项目也是如此。我认为这个问题是在模板的调用在模板中。在上下文中的项目不会增加?我应该交出一个参数来确定我们正在对哪些项目?

总之,这是我想出了:

<xsl:for-each select="tbody/tr">
    <xsl:if test="th">
        <xsl:element name="group">
            <xsl:attribute name="name"><xsl:value-of select="th"/></xsl:attribute>
            <xsl:call-template name="item"/>
        </xsl:element>
    </xsl:if>
</xsl:for-each>

<xsl:template name="item">
    <xsl:element name="item">
        <xsl:attribute name="attribute1"><xsl:value-of select="following-sibling::tr[1]/td[1]"/></xsl:attribute>
        <xsl:attribute name="attribute2"><xsl:value-of select="following-sibling::tr[1]/td[2]"/></xsl:attribute>
        <xsl:attribute name="attribute2"><xsl:value-of select="following-sibling::tr[1]/td[3]"/></xsl:attribute>
    </xsl:element>
    <!-- When the next element has not got a TH tag, continue with invoking this template -->
    <xsl:if test="count(following-sibling::tr[1]/th) != 1">
        <xsl:call-template name="item"/>
    </xsl:if>
</xsl:template>

这是如何实现这欢迎任何建议!

有帮助吗?

解决方案

的备选解决方案,安装用于进行可变属性计数且无需递归。

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:template match="table">
    <groups>
      <xsl:apply-templates select="tbody/tr[th]"/>
    </groups>
  </xsl:template>

  <xsl:template match="tr[th]">
    <group name="{th}">
      <xsl:apply-templates select="
        following-sibling::tr[not(th)][
          generate-id(preceding-sibling::tr[th][1]) = generate-id(current())
        ]
      "/>
    </group>
  </xsl:template>

  <xsl:template match="tr">
    <item>
     <xsl:apply-templates select="td" />
    </item>
  </xsl:template>

  <xsl:template match="td">
    <xsl:attribute name="attribute{position()}">
      <xsl:value-of select="." />
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

其他提示

究其原因,当你调用模板这种情况下不增加“项”递归是XS:调用模板总是通过当前上下文项的上下文。所以你可能看到的,只是变换进入无限递归。

假设你总是需要产生完全相同三个属性,你甚至不需要递归。

尝试这种情况:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:template match="table">
        <groups>
            <xsl:apply-templates select="tbody/tr[th]"/>
        </groups>
    </xsl:template>

    <xsl:template match="tr[th]">
        <xsl:variable name="id" select="generate-id(.)"/>
        <group name="{string(th)}">
            <xsl:apply-templates
                select="following-sibling::tr[not(th)][generate-id(preceding-sibling::tr[th][1]) = $id]"/>
        </group>
    </xsl:template>

    <xsl:template match="tr">
        <item attribute1="{td[1]}" attribute2="{td[2]}" attribute3="{td[3]}" />                    
    </xsl:template>

</xsl:stylesheet>

此工作通过应用模板来每个标题行。每个那些模板的使用了复杂的xpath称之为“其”下面的行,这是任何以下具有该特定行,因为它的第一行之前的与报头兄弟行。

当然,如果属性的数量而变化,则需要递归存在和增加通过指示所述位置的参数。

有一对夫妇为XSLT分组,其中一个是递归的,就像你在做建立的方法。另一种方法被称为Muenchian分组的。一个好的写了是这里

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top