Note that there are some explanatory texts on larger screens.

plurals
  1. POXpath in XSLT: select elements that are between 2 other elements, part II
    primarykey
    data
    text
    <p>As similar to this question (there are more related entries, however as a new user I can only post one URL): <a href="https://stackoverflow.com/questions/1489326/xpath-get-elements-that-are-between-2-elements">Xpath Get elements that are between 2 elements</a></p> <p>I have a question regarding the selection of set of elements that occur between 'other / delimiting' elements. This situation occurs when trying to transform a flat HTML table to a hierarchic XML structure using XSLT. I tried using recursion in the templates, but saxon refused to accept this as it resulted in a dead-lock, most probably my fault, but let's start at the beginning. </p> <p>First the source data is the HTML table:</p> <pre><code>&lt;table &gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;Column 1&lt;/th&gt; &lt;th&gt;Column 2&lt;/th&gt; &lt;th&gt;Column 3&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th colspan="3" &gt;Group 1&lt;/th&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;attribute 1.1.1&lt;/td&gt; &lt;td&gt;attribute 1.1.3&lt;/td&gt; &lt;td&gt;attribute 1.1.2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;attribute 1.2.1&lt;/td&gt; &lt;td&gt;attribute 1.2.2&lt;/td&gt; &lt;td&gt;attribute 1.2.3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;attribute 1.3.1&lt;/td&gt; &lt;td&gt;attribute 1.3.2&lt;/td&gt; &lt;td&gt;attribute 1.3.3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;th colspan="3" &gt;Group 2&lt;/th&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;attribute 2.1.1&lt;/td&gt; &lt;td&gt;attribute 2.1.3&lt;/td&gt; &lt;td&gt;attribute 2.1.2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;attribute 2.2.1&lt;/td&gt; &lt;td&gt;attribute 2.2.2&lt;/td&gt; &lt;td&gt;attribute 2.2.3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;attribute 2.3.1&lt;/td&gt; &lt;td&gt;attribute 2.3.2&lt;/td&gt; &lt;td&gt;attribute 2.3.3&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; </code></pre> <p>The targeted output in XML would be:</p> <pre><code> &lt;groups&gt; &lt;group name="Group 1"&gt; &lt;item attribute1="attribute 1.1.1" attribute2="attribute 1.1.3" attribute3="attribute 1.1.2"/&gt; &lt;item attribute1="attribute 1.2.1" attribute2="attribute 1.2.2" attribute3="attribute 1.2.3"/&gt; &lt;item attribute1="attribute 1.3.1" attribute2="attribute 1.3.2" attribute3="attribute 1.3.3"/&gt; &lt;/group&gt; &lt;group name="Group 2"&gt; &lt;item attribute1="attribute 2.1.1" attribute2="attribute 2.1.3" attribute3="attribute 2.1.2"/&gt; &lt;item attribute1="attribute 2.2.1" attribute2="attribute 2.2.2" attribute3="attribute 2.2.3"/&gt; &lt;item attribute1="attribute 2.3.1" attribute2="attribute 2.3.2" attribute3="attribute 2.3.3"/&gt; &lt;/group&gt; &lt;/groups&gt; </code></pre> <p>So I want to have all the item entries, (TR elements) and add them to a group. This basically comes down to select all following-sibling TR elements until we encounter one that has a TH element as a child. If I could only determine the position of this first TR that has a TH child, indicating a new heading for a group, this could be done with: </p> <pre><code>&lt;xsl:for-each select="tbody/tr"&gt; &lt;xsl:if test="th"&gt; &lt;xsl:element name="group"&gt; &lt;xsl:attribute name="name"&gt;&lt;xsl:value-of select="th"/&gt;&lt;/xsl:attribute&gt; &lt;xsl:for-each select="following-sibling::tr[position() &lt; $positionOfNextThElement]"&gt; &lt;xsl:call-template name="item"/&gt; &lt;/xsl:for-each&gt; &lt;/xsl:element&gt; &lt;/xsl:if&gt; &lt;/xsl:for-each&gt; </code></pre> <p>However, I am not able to determine the position of the first encountered TR/TH tag. </p> <p>As stated I tried working with recursion in templates: always call the "item" template and in this template determine whether we want to invoke it on the next item as well. I think the problem is in the invocation of the template from within the template. The item in context does not increase? Should I hand over a parameter to determine what item we are working on?</p> <p>Anyhow, this was what I came up with: </p> <pre><code>&lt;xsl:for-each select="tbody/tr"&gt; &lt;xsl:if test="th"&gt; &lt;xsl:element name="group"&gt; &lt;xsl:attribute name="name"&gt;&lt;xsl:value-of select="th"/&gt;&lt;/xsl:attribute&gt; &lt;xsl:call-template name="item"/&gt; &lt;/xsl:element&gt; &lt;/xsl:if&gt; &lt;/xsl:for-each&gt; &lt;xsl:template name="item"&gt; &lt;xsl:element name="item"&gt; &lt;xsl:attribute name="attribute1"&gt;&lt;xsl:value-of select="following-sibling::tr[1]/td[1]"/&gt;&lt;/xsl:attribute&gt; &lt;xsl:attribute name="attribute2"&gt;&lt;xsl:value-of select="following-sibling::tr[1]/td[2]"/&gt;&lt;/xsl:attribute&gt; &lt;xsl:attribute name="attribute2"&gt;&lt;xsl:value-of select="following-sibling::tr[1]/td[3]"/&gt;&lt;/xsl:attribute&gt; &lt;/xsl:element&gt; &lt;!-- When the next element has not got a TH tag, continue with invoking this template --&gt; &lt;xsl:if test="count(following-sibling::tr[1]/th) != 1"&gt; &lt;xsl:call-template name="item"/&gt; &lt;/xsl:if&gt; &lt;/xsl:template&gt; </code></pre> <p>Any suggestions on how to realize this are welcome!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload