Группировка в XSLT 2.0 аналогична задачам br to p
В XSLT 1.0 общий вопрос на форумах заключался в том, как преобразовать плоский HTML в иерархический XML, который много раз сводился к тому, чтобы вложить текст между <br />
теги в <p>
теги.
У меня есть похожая проблема, которую, я думаю, я частично решил с помощью XSLT 2.0, но для меня это новый подход, и я хотел бы получить второе мнение.
Источник XHTML имеет <span class="pageStart"></span>
разбросаны по всему. Они могут появляться в нескольких разных родительских узлах. Я хочу обернуть все узлы между одним маркером начала страницы и следующим <page>
узел. В настоящее время у меня есть решение:
<xsl:template match="*[child::span[@class='pageStart']]">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:for-each-group select="node()"
group-starting-with="span[@class='pageStart']">
<page>
<xsl:apply-templates select="current-group()"/>
</page>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
В этом есть как минимум один недостаток - родительский узел маркера получает <page>
как дочерний узел, когда я этого не хочу. В других работах, если есть <div>
где есть маркер дочерней страницы, <page>
узел создается как непосредственный потомок <div>
в дополнение к местам, которые я ожидаю.
Я надеялся, что смогу просто сделать правило шаблона <xsl:template match="span[@class='pageStart']">
но current-group() кажется пустым, что бы я ни пытался. Здравый смысл, который я попробовал, был <xsl:for-each-group select="node()" group-starting-with="span[@class='pageStart']">
,
Есть ли более простой способ решить эту проблему, которую я упускаю?
РЕДАКТИРОВАТЬ
Вот пример ввода:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head></head>
<body>
<span class="pageStart"/>
<p>...</p>
<div>...</div>
<img />
<p></p>
<span class="pageStart"/>
<div>...</div>
<span class="pageStart"/>
<p>...</p>
<div>
<span class="pageStart"/>
<p>...</p>
<p>...</p>
<span class="pageStart"/>
<div>...</div>
<img/>
</div>
</body>
</html>
Я предполагаю, что последние две вложенные страницы делают эту проблему более сложной, поэтому я был бы очень рад получить это в качестве вывода или что-то близкое:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head></head>
<body>
<page>
<span class="pageStart"/>
<p>...</p>
<div>...</div>
<img />
<p></p>
</page>
<page>
<span class="pageStart"/>
<div>...</div>
</page>
<page>
<span class="pageStart"/>
<p>...</p>
<div>
<page>
<span class="pageStart"/>
<p>...</p>
<p>...</p>
</page>
<page>
<span class="pageStart"/>
<div>...</div>
<img/>
</page>
</div>
</page>
</body>
</html>
1 ответ
Это преобразование:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[span/@class='pageStart']">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each-group select="node()"
group-starting-with="span[@class='pageStart']">
<page>
<xsl:apply-templates select="current-group()"/>
</page>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному документу XML:
<html>
<head></head>
<body>
<span class="pageStart"/>
<p>...</p>
<div>...</div>
<img />
<p></p>
<span class="pageStart"/>
<div>...</div>
<span class="pageStart"/>
<p>...</p>
<div>
<span class="pageStart"/>
<p>...</p>
<p>...</p>
<span class="pageStart"/>
<div>...</div>
<img/>
</div>
</body>
</html>
дает желаемый, правильный результат:
<html>
<head/>
<body>
<page>
<span class="pageStart"/>
<p>...</p>
<div>...</div>
<img/>
<p/>
</page>
<page>
<span class="pageStart"/>
<div>...</div>
</page>
<page>
<span class="pageStart"/>
<p>...</p>
<div>
<page>
<span class="pageStart"/>
<p>...</p>
<p>...</p>
</page>
<page>
<span class="pageStart"/>
<div>...</div>
<img/>
</page>
</div>
</page>
</body>
</html>