Select all of an element between the current element and the next of the current element

天涯浪子 提交于 2019-12-11 11:11:29

问题


Using XSLT 1.0 (preferably), How can I select all of an element which occurs between the current element and the next time the current element occurs?

Say I have this XML (edited):

<root>
    <heading_1>Section 1</heading_1>
    <para>...</para>
    <list_1>...</list_1>
    <heading_2>Section 1.1</heading_2>
    <para>...</para>
    <heading_3>Section 1.1.1</heading_3>
    <para>...</para>
    <list_1>...</list_1>
    <heading_2>Section 1.2</heading_2>
    <para>...</para>
    <footnote>...</footnote>
    <heading_1>Section 2</heading_1>
    <para>...</para>
    <list_1>...</list_1>
    <heading_2>Section 2.1</heading_2>
    <para>...</para>
    <list_1>...</list_1>
    <list_2>...</list_2>
    <heading_3>Seciton 2.1.1</heading_3>
    <para>...</para>
    <heading_2>Section 2.2</heading_2>
    <para>...</para>
    <footnote>...</footnote>
</root>

When processing heading_1 I want to select all of heading_2 between the heading I am processing and the next heading_1. The same for selecting heading_3 when processing heading_2 etc. you get the picture.


回答1:


You can use this:

following-sibling::heading_2[generate-id(preceding-sibling::heading_1[1]) = 
                             generate-id(current())]

Working example:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="heading_1" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="heading_1">
    <xsl:copy>
      <xsl:apply-templates
        select="following-sibling::heading_2[generate-id(
                                                preceding-sibling::heading_1[1]) = 
                                             generate-id(current())]" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="heading_2">
    <xsl:copy>
      <xsl:apply-templates
        select="following-sibling::heading_3[generate-id(
                                                preceding-sibling::heading_2[1]) = 
                                             generate-id(current())]" />
    </xsl:copy>
  </xsl:template>    
</xsl:stylesheet>

Result when run on your sample input:

<root>
  <heading_1>
    <heading_2>
      <heading_3>...</heading_3>
    </heading_2>
    <heading_2 />
  </heading_1>
  <heading_1>
    <heading_2>
      <heading_3>...</heading_3>
    </heading_2>
    <heading_2 />
  </heading_1>
</root>



回答2:


Try the below XPath to select the heading2 when processing heading 1.

(/root/heading_1/following-sibling::heading_1/preceding-sibling::heading_2) | (/root/heading_1[preceding-sibling::heading_1]/following-sibling::heading_2)


来源:https://stackoverflow.com/questions/16145859/select-all-of-an-element-between-the-current-element-and-the-next-of-the-current

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!