使用 XSLT 1.0 包装标头的同级元素

发布于 2024-10-20 19:12:38 字数 553 浏览 2 评论 0原文

我正在使用 PHP 中的 XSLT 1.0,并且希望将标题 (h2) 之后的所有同级元素包装到 div 中,以便我可以切换它们。

输入看起来像这样

...
<h2>Nth title</h2>
<first child>...</first child>
...
<last child>...</last child>
<h2>N+1st title</h2>
...

,输出应该是

...
<h2>Nth title</h2>
<div>
  <first child>...</first child>
  ...
  <last child>...</last child>
</div>
<h2>N+1st title</h2>
...

Is there a way to do this in XSLT 1.0?

I'm working with XSLT 1.0 from PHP and want to wrap all the sibling elements after a heading (h2) into a div so I can toggle them.

The input would look like

...
<h2>Nth title</h2>
<first child>...</first child>
...
<last child>...</last child>
<h2>N+1st title</h2>
...

and the output should be

...
<h2>Nth title</h2>
<div>
  <first child>...</first child>
  ...
  <last child>...</last child>
</div>
<h2>N+1st title</h2>
...

Is there a way to do this in XSLT 1.0?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

自控 2024-10-27 19:12:38

此转换:

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

 <xsl:key name="kFollowing" match="node()[not(self::h2)]"
  use="generate-id(preceding-sibling::h2[1])"/>

 <xsl:template match="node()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="h2">
  <xsl:call-template name="identity"/>
  <div>
   <xsl:apply-templates mode="copy"
       select="key('kFollowing', generate-id())"/>
  </div>
 </xsl:template>

 <xsl:template match="node()[not(self::h2)][preceding-sibling::h2]"/>

 <xsl:template match="node()" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>

应用于此 XML 文档时:

<html>
    <h2>Nth title</h2>
    <first-child>...</first-child> ... 
    <last-child>...</last-child>
    <h2>N+1st title</h2> ...
    <x/>
     <y/>
     <z/>
</html>

产生所需的正确结果:

<html>
   <h2>Nth title</h2>
   <div>
      <first-child>...</first-child> ... 

      <last-child>...</last-child>
   </div>
   <h2>N+1st title</h2>
   <div> ...

      <x></x>
      <y></y>
      <z></z>
   </div>
</html>

说明

  1. 身份规则/模板“按原样”复制每个节点。

  2. h2 元素的身份规则被覆盖。这里的操作是复制 h2 元素,然后输出一个 div 并在其中将模板(在特殊模式下)应用到所有节点(不是 >h2 本身),其中此 h2 元素是第一个前同级 h2 元素。

  3. 要在上一步中包含的节点可以方便地定义为 指令。

  4. 为了阻止div中包裹的节点被身份规则再次输出,我们提供了一个匹配此类节点的模板,该模板会简单地忽略它们。

This transformation:

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

 <xsl:key name="kFollowing" match="node()[not(self::h2)]"
  use="generate-id(preceding-sibling::h2[1])"/>

 <xsl:template match="node()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="h2">
  <xsl:call-template name="identity"/>
  <div>
   <xsl:apply-templates mode="copy"
       select="key('kFollowing', generate-id())"/>
  </div>
 </xsl:template>

 <xsl:template match="node()[not(self::h2)][preceding-sibling::h2]"/>

 <xsl:template match="node()" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>

when applied on this XML document:

<html>
    <h2>Nth title</h2>
    <first-child>...</first-child> ... 
    <last-child>...</last-child>
    <h2>N+1st title</h2> ...
    <x/>
     <y/>
     <z/>
</html>

produces the wanted, correct result:

<html>
   <h2>Nth title</h2>
   <div>
      <first-child>...</first-child> ... 

      <last-child>...</last-child>
   </div>
   <h2>N+1st title</h2>
   <div> ...

      <x></x>
      <y></y>
      <z></z>
   </div>
</html>

Explanation:

  1. The identity rule/template copies every node "as-is".

  2. The identity rule is overriden for h2 elements. Here the action is to copy the h2 element and then to output a div and inside it to apply templates (in a special mode) to all nodes (that are not h2 themselves) for which this h2 element is the first preceding-sibling h2 element.

  3. The nodes to include in the previous step are conveniently defined as an <xsl:key> instruction.

  4. In order to stop the nodes that are wrapped in div to be output again by the identity rule, we provide a template matching such nodes, that simply ignores them.

月亮坠入山谷 2024-10-27 19:12:38

是的。制作一个匹配h2元素的模板;在该模板中,您可以使用以下 xpath 表达式选择下一个 h2 之前的所有以下同级:following-sibling::*[count(preceding-sibling::h2[1] | current()) = 1].

Yes. Make a template that matches h2 elements; within that template, you can select all following siblings before the next h2 using this xpath expression: following-sibling::*[count(preceding-sibling::h2[1] | current()) = 1].

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文