How can I group these ul elements into ul and li elements XSL

Anyone can help me with xsl? I don’t know how to achieve this:

This is my sample input xml file:

<?xml version="1.0" encoding="UTF-8"?>
<export>
   <article>
      <h4>Kernpunkte des Discours sind:</h4>
      <ul>eine Erkenntnistheorie, die nur das als richtig akzeptiert, was durch die eigene schrittweise Analyse und logische Reflexion als plausibel verifiziert wird,</ul>
      <ul>eine Ethik, gemäß der das Individuum sich im Sinne bewährter gesellschaftlicher Konventionen pflichtbewusst und moralisch zu verhalten hat,</ul>
      <ul>eine Metaphysik, die zwar (durch logischen Beweis) die Existenz eines vollkommenen Schöpfer-Gottes annimmt, aber kirchenartigen Institutionen wenig Raum lässt,</ul>
      <ul>eine Physik, die die Natur als durch zwar gottgegebene, aber allgemein gültige Gesetze geregelt betrachtet und dem Menschen ihre rationale Erklärung und damit letztlich ihre Beherrschung zur Aufgabe macht.</ul>
   </article>
</export>

I need to group all <ul> elements into <ul><li>…</li></ul> elements so that it will become like this:

<?xml version="1.0" encoding="UTF-8"?>
<export>
   <article>
      <h4>Kernpunkte des Discours sind:</h4>
      <ul>
         <li>eine Erkenntnistheorie, die nur das als richtig akzeptiert, was durch die eigene schrittweise Analyse und logische Reflexion als plausibel verifiziert wird,</li>
         <li>eine Ethik, gemäß der das Individuum sich im Sinne bewährter gesellschaftlicher Konventionen pflichtbewusst und moralisch zu verhalten hat,</li>
         <li>eine Metaphysik, die zwar (durch logischen Beweis) die Existenz eines vollkommenen Schöpfer-Gottes annimmt, aber kirchenartigen Institutionen wenig Raum lässt,</li>
         <li>eine Physik, die die Natur als durch zwar gottgegebene, aber allgemein gültige Gesetze geregelt betrachtet und dem Menschen ihre rationale Erklärung und damit letztlich ihre Beherrschung zur Aufgabe macht.</li>
      </ul>
   </article>
</export>

I tried something like this:

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

  <xsl:template match="/">
    <export>
      <article>
        <xsl:apply-templates />
      </article>
    </export>
  </xsl:template>

  <xsl:template match="ul">
    <ul>
      <xsl:apply-templates />
    </ul>
  </xsl:template>

  <xsl:template match="ul/text()">
    <li>
      <xsl:value-of select="." />
    </li>
  </xsl:template>

</xsl:stylesheet>

But it does not work as expected:

<?xml version="1.0" encoding="UTF-8"?>
<export>
   <article>
      Kernpunkte des Discours sind:
      <ul>
         <li>eine Erkenntnistheorie, die nur das als richtig akzeptiert, was durch die eigene schrittweise Analyse und logische Reflexion als plausibel verifiziert wird,</li>
      </ul>
      <ul>
         <li>eine Ethik, gemäß der das Individuum sich im Sinne bewährter gesellschaftlicher Konventionen pflichtbewusst und moralisch zu verhalten hat,</li>
      </ul>
      <ul>
         <li>eine Metaphysik, die zwar (durch logischen Beweis) die Existenz eines vollkommenen Schöpfer-Gottes annimmt, aber kirchenartigen Institutionen wenig Raum lässt,</li>
      </ul>
      <ul>
         <li>eine Physik, die die Natur als durch zwar gottgegebene, aber allgemein gültige Gesetze geregelt betrachtet und dem Menschen ihre rationale Erklärung und damit letztlich ihre Beherrschung zur Aufgabe macht.</li>
      </ul>
   </article>
</export>

Can someone who is very good with xsl help me with my request?

Thanks in advance!

Regards,
Noel

>Solution :

I would try this way:

<xsl:stylesheet version="3.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="article">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="name()"> 
            <xsl:choose>
                <xsl:when test="self::ul">
                    <ul>
                        <xsl:apply-templates select="current-group()"/>
                    </ul>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

<xsl:template match="ul">
    <li>
        <xsl:apply-templates/>
    </li>
</xsl:template>

</xsl:stylesheet>

This is in XSLT 3.0.


If article has only h4 and ul child elements, then you can do only:

<xsl:stylesheet version="3.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="article">
    <xsl:copy>
        <xsl:apply-templates select="h4"/>
        <ul>
            <xsl:apply-templates select="ul"/>
        </ul>
    </xsl:copy>
</xsl:template>

<xsl:template match="ul">
    <li>
        <xsl:apply-templates/>
    </li>
</xsl:template>

</xsl:stylesheet>

Leave a Reply