0

My question is related to: XSLT with overlapping elements? – but the proposed solution is not working for me.

Input

I have some TEI-XML encoded like this:

<delSpan spanTo="#abcbb6b8-b7bd-4b96-93c1-0a34500e12c0"/>
<lg>
    <l>some text that is deleted</l>
</lg>
<lg>
    <l>much more text</l>
    <l>another line of text</l>
</lg>
<anchor xml:id="abcbb6b8-b7bd-4b96-93c1-0a34500e12c0"/>

I want to process it with XSL and my output should look like:

<div class="delSpan">
    <div class="lg">
        <span>some text that is deleted</span>
    </div>
    <div class="lg">
        <span>much more text</span>
        <span>another line of text</span>
    </div>
</div>

XSLT At the moment I am trying to work with the following templates:

<xsl:template match="tei:delSpan">
    <xsl:variable name="id">
        <xsl:value-of select="substring-after(@spanTo, '#')"/>
    </xsl:variable>
    <xsl:for-each-group select="*" group-ending-with="tei:anchor[@xml:id=$id]">
        <div class="delSpan">
            <xsl:apply-templates />
        </div>
    </xsl:for-each-group>
</xsl:template>

<xsl:template match="tei:lg">
    <div class="lg">
        <xsl:apply-templates/>
    </div>
</xsl:template>

<xsl:template match="tei:l">
    <span>
        <xsl:apply-templates/>
    </span>
</xsl:template>

But this just produces the following output:

<div class="lg">
        <span>some text that is deleted</span>
    </div>
    <div class="lg">
        <span>much more text</span>
        <span>another line of text</span>
    </div>

So I am asking myself if there is any common and easy solution to deal with so called milestone-elements and process like described above?

B Polit
  • 162
  • 8
  • It seems your code in a template matching `tei:delSpan` with `xsl:for-each-group select="*" ` tries to process any child elements of the `delSpan`, only it is an empty element in your sample so it doesn't have any children. I don't know the exact structure but usually matching on the parent element of the `delSpan` and then using `for-each-group select="node()" group-starting-with="tei:delSpan"` with a nested `group-ending-with` to grab the referenced `tei:anchor` seems like an easier approach. Or can the `delSpan` and `anchor` elements at different levels? – Martin Honnen Feb 06 '20 at 14:45
  • I am not sure, if I'm getting it right. Do you mean it this way?
    – B Polit Feb 06 '20 at 14:56
  • And yes most of the time `delSpan`and `anchor` are on the same level (child elements of an `div`). The solutions of the preceding comment produces empty content. – B Polit Feb 06 '20 at 15:00
  • It is hard exchanging code in comments, I have posted some attempt of an answer to have a formatted example, if you want to add any attempt and their failed results then please edit your question where you can present them in a formatted and readable way. – Martin Honnen Feb 06 '20 at 15:12

1 Answers1

1

If you move the for-each-group to the parent element of any delSpan (or any element you expect to apply the wrapping to) then it would look like

  <xsl:template match="*[delSpan]">
      <xsl:for-each-group select="*" group-starting-with="delSpan">
          <xsl:choose>
              <xsl:when test="self::delSpan">
                  <xsl:variable name="id-ref" select="substring(@spanTo, 2)"/>
                  <div class="{local-name()}">
                      <xsl:for-each-group select="current-group() except ." group-ending-with="id($id-ref)">
                          <xsl:choose>
                              <xsl:when test="current-group()[last()] is id($id-ref)">
                                  <xsl:apply-templates select="current-group()[not(position() = last())]"/>
                              </xsl:when>
                              <xsl:otherwise>
                                  <xsl:apply-templates select="current-group()"/>
                              </xsl:otherwise>
                          </xsl:choose>
                      </xsl:for-each-group>
                  </div>
              </xsl:when>
              <xsl:otherwise>
                  <xsl:apply-templates select="current-group()"/>
              </xsl:otherwise>
          </xsl:choose>
      </xsl:for-each-group>
  </xsl:template>

https://xsltfiddle.liberty-development.net/pPJ9hEk/1

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110