Я пытаюсь сгруппировать следующий html-контент:
вход
<?xml version="1.0" encoding="UTF-8"?>
<html>
<body>
<h2>Steps for grouping in the Muench method</h2>
<p class="step">Define a <code>key</code> for the property we want
to use for grouping.</p>
<p class="step">Select all of the nodes ...</p>
<p class="substep">Select all of the nodes ...</p>
<p class="result">Select all of the nodes ...</p>
<p class="substep">Select all of the nodes ...</p>
<p class="step">For each unique grouping value ...</p>
<h2>Steps for grouping in XSLT 2.0</h2>
<p class="step">Define an XPath expression ...</p>
<p class="substep">Select all of the nodes ...</p>
<p class="substep">Instead of dealing with each ...</p>
</body>
</html>
в следующий вывод
Я просмотрел пару ответов здесь, прежде чем публиковать их здесь. Они дали идею о том, как сгруппировать следующих братьев и сестер с целевым элементом. Например, когда я хочу сгруппировать элемент с @result внутри подшага. И каждый подшаг внутри шага.
<body>
<h2>Steps for grouping in the Muench method</h2>
<step>
<p class="step">Define a <code>key</code> for the property we want to use for
grouping.</p>
</step>
<step>
<p class="step">Select all of the nodes ...</p>
<substep>
<p class="substep">Select all of the nodes ...</p>
<p class="result">Select all of the nodes ...</p>
</substep>
<substep>
<p class="substep">Select all of the nodes ...</p>
</substep>
</step>
<step>
<p class="step">For each unique grouping value ...</p>
<h2>Steps for grouping in XSLT 2.0</h2>
</step>
<step>
<p class="step">Define an XPath expression ...</p>
<substep>
<p class="substep">Select all of the nodes ...</p>
</substep>
<substep>
<p class="substep">Instead of dealing with each ...</p>
</substep>
</step>
</body>
Что я сделал до сих пор
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:key name="step" match="p" use="@class"/>
<xsl:template match="/">
<body>
<xsl:variable name="steps">
<xsl:for-each-group select="html/body/*" group-starting-with="p[@class = 'step']">
<xsl:choose>
<xsl:when test="current-group()[self::p[@class = 'step']]">
<step>
<xsl:copy-of select="current-group()"/>
</step>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$steps" mode="fix.step"/>
</body>
</xsl:template>
<xsl:template match="node()" mode="fix.step">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="step" mode="fix.step">
<step>
<xsl:for-each-group select="*" group-starting-with="p[@class = 'substep']">
<xsl:choose>
<xsl:when test="current-group()[self::p[@class = 'substep']]">
<substep>
<xsl:copy-of select="current-group()"/>
</substep>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</step>
</xsl:template>
</xsl:stylesheet>
Вопросы
Есть ли лучший способ добиться того же результата?
несколько предостережений
Данный входной файл является только примером. Между элементами @step и @substep может быть много элементов, отличных от @step и @substep. И они должны быть сгруппированы внутри шага или подшага в зависимости от их положения. Например, следующим может быть другой вариант входного файла:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<body>
<h2>Steps for grouping in the Muench method</h2>
<p class="step">Define a <code>key</code> for the property we want
to use for grouping.</p>
<p class="step">Select all of the nodes ...</p>
<p class="result">Select all of the nodes ...</p>
<image @href="image.pn"/>
<p class="substep">Select all of the nodes ...</p>
<p class="substep">Select all of the nodes ...</p>
<p class="result">Select all of the nodes ...</p>
<p class="substep">Select all of the nodes ...</p>
<p class="step">For each unique grouping value ...</p>
<h2>Steps for grouping in XSLT 2.0</h2>
<p class="step">Define an XPath expression ...</p>
<p class="substep">Select all of the nodes ...</p>
<p class="substep">Instead of dealing with each ...</p>
</body>
</html>
Правила
- When a list item at level 1 has following siblings p/@class=ListContinue or p/@class=ListNote or p/@class=ListBullet2, all such adjacent elements should be wrapped in
- as well except where the p/@class = BodyText or p/@class=Note.
- When a list item at level 2 has following siblings p/@class=ListContinue2 or p/@class=ListNote, all such adjacent elements should be wrapped in
- as well except where the p/@class = BodyText or p/@class=Note or p/@class=ListBullet.
Таким образом, вся информация, относящаяся к конкретному элементу списка, помещается в li. Та же логика применима ко всем li независимо от глубины. Это то, что мне трудно достичь.