Merging element sequences in XSLT

I have a bunch of auto-generated HTML doing such stupid things:

 <p>Hey it <em>italic</em><em>italic</em>!</p>

And I would like to sing this:

 <p>Hey it <em>italicitalic</em>!</p>

My first attempt was in this direction ...

<xsl:template match="em/preceding::em">
    <xsl:value-of select="$OPEN_EM"/>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="em/following::em">
    <xsl:apply-templates/>
    <xsl:value-of select="$CLOSE_EM"/>
</xsl:template>

But, apparently, the XSLT specification, in its grandest kindness, prohibits the use of standard XPath axes precedingor followingtemplates. (And that will require some tweaking to handle three ems per line anyway.)

, XSLT replace('</em><em>', '') $LANGUAGE_OF_CHOICE ? : <em>, - (, , ), , , XML, <em> . , ems ( ems), .

(, , xslt?, , . XSLT 2, , .)

+3
2

:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="em">
        <em>
            <xsl:call-template name="merge"/>
        </em>
        <xsl:apply-templates
             select="following-sibling::node()[not(self::em)][1]"/>
    </xsl:template>
    <xsl:template match="node()" mode="merge"/>
    <xsl:template match="em" name="merge" mode="merge" >
        <xsl:apply-templates select="node()[1]"/>
        <xsl:apply-templates select="following-sibling::node()[1]" 
                             mode="merge"/>
    </xsl:template>
</xsl:stylesheet>

:

<p>Hey it <em>italicitalic</em>!</p>

: graneid ( , node node); em ( , node by node), wraping call merge, , em; em merge ( merge), aplly ( node, ), merge; "", , em ( node ) .

+2

:

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

 <xsl:key name="kFollowing"
  match="em[preceding-sibling::node()[1][self::em]]"
  use="generate-id(preceding-sibling::node()[not(self::em)][1])"/>

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

 <xsl:template match=
    "em[following-sibling::node()[1][self::em]
      and
        not(preceding-sibling::node()[1][self::em])
       ]">
   <em>
     <xsl:apply-templates select=
     "node()
     |
      key('kFollowing',
           generate-id(preceding-sibling::node()[1])
          )/node()"/>
   </em>
 </xsl:template>
 <xsl:template match=
 "em[preceding-sibling::node()[1][self::em]]"/>
</xsl:stylesheet>

XML- ( , em):

<p>Hey it <em>italic1</em><em>italic2</em><em>italic3</em>!</p>

, :

<p>Hey it <em>italic1italic2italic3</em>!</p>

:

  • node .

  • em.

  • em , em.

  • em.

+2

Source: https://habr.com/ru/post/1772044/


All Articles