【问题标题】:How to select a node and its siblings until the same node from the start occurs如何选择一个节点及其兄弟节点,直到从一开始就出现同一个节点
【发布时间】:2014-11-04 15:53:24
【问题描述】:

这可能是个棘手的问题。

我有这份文件:

<html>
   <h1>title1</h1>
   <p>content</p>
   <ul>
      <li>item</li>
   </ul>
   <h1>title2</h1>
   <p>content</p>
   <p>another content</p>
   <h1>title3</h1>
   <ol>
      <li><p>text</p></li>
   </ol>
</html>

这个例子表明我有一些 html,其中“部分”被标题划分。它是标题,然后是各种元素的组合,然后又是标题。

我希望使用 XSLT 2 用 div 包装这些部分。

所以,我想使用&lt;h1&gt; 标题来选择组。基本上分组规则是:

  • 选择h1 他的所有兄弟姐妹,直到出现另一个h1

“和” 上的这种强调非常重要,因为我想出了 XPath 公式,它仅在 h1 节点之间选择节点,或者从第一个到最后一个 h1 选择忽略 h1它们之间。我也需要得到那个标题。我认为使用 XPath 实现这一点并不难,但我无法让它发挥作用。

为了更好地理解,它应该是这样的:

<html>
   <div>
      <h1>title1</h1>
      <p>content</p>
      <ul>
         <li>item</li>
      </ul>
   </div>
   <div>
      <h1>title2</h1>
      <p>content</p>
      <p>another content</p>
   </div>
   <div>
      <h1>title3</h1>
      <ol>
         <li><p>text</p></li>
      </ol>
   </div>
</html>

【问题讨论】:

    标签: xslt xpath xslt-2.0 xpath-2.0 xslt-grouping


    【解决方案1】:

    您可以为此使用group-starting-with

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="html">
        <xsl:copy>
          <xsl:for-each-group select="node()" group-starting-with="h1">
            <div>
              <xsl:copy-of select="current-group()" />
            </div>
          </xsl:for-each-group>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    

    在您的样本上运行时,结果是:

    <html>
       <div>
          <h1>title1</h1>
          <p>content</p>
          <ul>
             <li>item</li>
          </ul>
       </div>
       <div>
          <h1>title2</h1>
          <p>content</p>
          <p>another content</p>
       </div>
       <div>
          <h1>title3</h1>
          <ol>
             <li>
                <p>text</p>
             </li>
          </ol>
       </div>
    </html>
    

    作为一些额外信息,如果您想使用group-by 来执行此操作,您可以这样做:

      <xsl:for-each-group select="node()" group-by="self::h1 | preceding-sibling::h1[1]">
    

    这应该会产生相同的结果。

    【讨论】:

    • 太棒了!我认为解决方案在 XPath 中,但这是错误的猜测。 XSLT 提供了这样优雅、简单的综合解决方案。谢谢!
    • &lt;xsl:for-each select="current-group()"&gt;&lt;xsl:copy-of select="." /&gt; 应缩短为 &lt;xsl:copy-of select="current-group()/&gt;
    • @MartinHonnen 谢谢!我很少使用 XSLT 2.0,也没有想到这一点。
    猜你喜欢
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    相关资源
    最近更新 更多