XSLT:将分组 html 元素移动到部分级别 [英] XSLT: moving a grouping html elements into section levels
问题描述
我正在尝试编写一个 XSLT,根据标题级别将 HTML 文件组织到不同的节级别.这是我的输入:
I'm trying to write an XSLT that organizes an HTML file into different section levels depending on the header level. Here is my input:
<html>
<head>
<title></title>
</head>
<body>
<h1>HEADER 1 CONTENT</h1>
<p>Level 1 para</p>
<p>Level 1 para</p>
<p>Level 1 para</p>
<p>Level 1 para</p>
<h2>Header 2 CONTENT</h2>
<p>Level 2 para</p>
<p>Level 2 para</p>
<p>Level 2 para</p>
<p>Level 2 para</p>
</body>
</html>
我目前正在使用一个相当简单的结构,因此这种模式暂时将保持不变.我需要这样的输出...
I'm working with a fairly simple structure at the moment so this pattern will be constant for the time-being. I need an output like this...
<document>
<section level="1">
<header1>Header 1 CONTENT</header1>
<p>Level 1 para</p>
<p>Level 1 para</p>
<p>Level 1 para</p>
<p>Level 1 para</p>
<section level="2">
<header2>Header 2 CONTENT</header2>
<p>Level 2 para</p>
<p>Level 2 para</p>
<p>Level 2 para</p>
<p>Level 2 para</p>
</section>
</section>
</document>
我一直在使用这个例子:Stackoverflow 答案
I had been working with this example: Stackoverflow Answer
但是,我无法让它完全满足我的需求.
However, I cannot get it to do exactly what I need.
我正在使用 Saxon 9 在 Oxygen 中为 dev 运行 xslt.我将在生产中使用 cmd/bat 文件.仍然是 Saxon 9.如果可能,我想最多处理 4 个嵌套的节级别.
I'm using Saxon 9 to run the xslt within Oxygen for dev. I'll be using a cmd/bat file in production. Still Saxon 9. I'd like to handle up to 4 nested section levels if possible.
非常感谢任何帮助!
我需要在此附加,因为我遇到了另一个规定.我之前可能应该想到这一点.
I need to append onto this as I've encountered another stipulation. I probably should have thought of this before.
我遇到以下代码示例
<html>
<head>
<title></title>
</head>
<body>
<p>Level 1 para</p>
<p>Level 1 para</p>
<p>Level 1 para</p>
<p>Level 1 para</p>
<h1>Header 2 CONTENT</h1>
<p>Level 2 para</p>
<p>Level 2 para</p>
<p>Level 2 para</p>
<p>Level 2 para</p>
</body>
</html>
如您所见, 是
的子代,而在我的第一个片段
中code> 始终是标题级别的子级.我想要的结果和上面一样,只是当我遇到
作为
的孩子时,它应该被包裹在
<;section level="1">
.
As you can see, the <p>
is a child of <body>
while in my first snippet, <p>
was always a child of a header level. My desired result is the same as above except that when I encounter <p>
as a child of <body>
, it should be wrapped in <section level="1">
.
<document>
<section level="1">
<p>Level 1 para</p>
<p>Level 1 para</p>
<p>Level 1 para</p>
<p>Level 1 para</p>
</section>
<section level="1">
<header1>Header 2 CONTENT</header1>
<p>Level 2 para</p>
<p>Level 2 para</p>
<p>Level 2 para</p>
<p>Level 2 para</p>
</section>
</document>
推荐答案
这是一个 XSLT 2.0 样式表:
Here is an XSLT 2.0 stylesheet:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf"
version="2.0">
<xsl:output indent="yes"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$elements" group-starting-with="*[local-name() eq concat('h', $level)]">
<xsl:choose>
<xsl:when test="self::*[local-name() eq concat('h', $level)]">
<section level="{$level}">
<xsl:element name="header{$level}"><xsl:apply-templates/></xsl:element>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/html">
<document>
<xsl:apply-templates select="body"/>
</document>
</xsl:template>
<xsl:template match="body">
<xsl:sequence select="mf:group(*, 1)"/>
</xsl:template>
</xsl:stylesheet>
它应该按照您的要求执行,尽管它不会停留在四个嵌套级别,而是只要找到 h[n]
元素就可以进行分组.
It should do what you asked for, although it does not stop at four nested levels but rather groups as long as it finds h[n]
elements.
这篇关于XSLT:将分组 html 元素移动到部分级别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!