XSLT:将分组html元素移动到部分级别 [英] XSLT: moving a grouping html elements into section levels

查看:109
本文介绍了XSLT:将分组html元素移动到部分级别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个XSLT,它根据标题级别将HTML文件组织到不同的部分级别。这里是我的输入:

 < html> 
< head>
< title>< / title>
< / head>
< body>
< h1> HEADER 1 CONTENT< / h1>
< p> 1级para< / p>
< p> 1级para< / p>
< p> 1级para< / p>
< p> 1级para< / p>

< h2>标题2内容< / h2>
< p>第2级para< / p>
< p>第2级para< / p>
< p>第2级para< / p>
< p>第2级para< / p>
< / body>
< / html>

目前我正在使用一个相当简单的结构,所以这个模式在当时是不变的-存在。我需要这样的输出......

 < document> 
< section level =1>
< header1>标题1 CONTENT< / header1>
< p> 1级para< / p>
< p> 1级para< / p>
< p> 1级para< / p>
< p> 1级para< / p>
< section level =2>
< header2>标题2 CONTENT< / header2>
< p>第2级para< / p>
< p>第2级para< / p>
< p>第2级para< / p>
< p>第2级para< / p>
< / section>
< / section>
< / document>

我一直在用这个例子:

但是,我无法做到我所需要的。

我正在使用Saxon 9在Oxygen for dev中运行xslt。我将在生产中使用cmd / bat文件。仍然Saxon 9.如果可能的话,我想处理最多4个嵌套部分级别。



任何帮助都非常感谢!



因为我遇到了另一个规定,所以我需要追加这个。我可能应该想到这一点。



我遇到以下代码示例:

 < HTML> 
< head>
< title>< / title>
< / head>
< body>
< p> 1级para< / p>
< p> 1级para< / p>
< p> 1级para< / p>
< p> 1级para< / p>

< h1>标题2 CONTENT< / h1>
< p>第2级para< / p>
< p>第2级para< / p>
< p>第2级para< / p>
< p>第2级para< / p>
< / body>
< / html>

正如您所见,< p> < p> 始终是一个孩子的标题级别。除了当我遇到< p> 作为< body> ,它应该包装在< section level =1> 中。

 <文件> 
< section level =1>
< p> 1级para< / p>
< p> 1级para< / p>
< p> 1级para< / p>
< p> 1级para< / p>
< / section>
< section level =1>
< header1>标题2 CONTENT< / header1>
< p>第2级para< / p>
< p>第2级para< / p>
< p>第2级para< / p>
< p>第2级para< / p>
< / section>
< / document>


解决方案

这是一个XSLT 2.0样式表:

 < 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-前缀=xs mf
version =2.0>

< xsl:output indent =yes/>

< xsl:function name =mf:groupas =node()*>
< xsl:param name =elementsas =element()*/>
< xsl:param name =levelas =xs:integer/>
< xsl:when test =self :: * [local-name()eq concat('h',$ level)]>
< section level ={$ level}>
< xsl:element name =header {$ level}>< xsl:apply-templates />< / xsl:element>
< / section>
< / xsl:when>
< xsl:otherwise>
< xsl:apply-templates select =current-group()/>
< / xsl:otherwise>
< / 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>
<文件>
< xsl:apply-templates select =body/>
< / document>
< / xsl:template>

< xsl:template match =body>
< xsl:sequence select =mf:group(*,1)/>
< / xsl:template>

< / xsl:stylesheet>

它应该按照您的要求进行操作,但它不会停在四个嵌套级别上,只要它找到 h [n] 元素。


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>

I had been working with this example: Stackoverflow Answer

However, I cannot get it to do exactly what I need.

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.

Any help is much appreciated!

I need to append onto this as I've encountered another stipulation. I probably should have thought of this before.

I'm encountering the following code sample

<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>

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>

解决方案

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>

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆