XPath1 - Selecting siblings

时间:2016-04-25 08:57:30

标签: xml xslt xpath

Given the following XML:

<p class='sectiontitle'>Examples</p>
<p class='paragraphtitle'>Example1</p>
<p>That's some text.</p>
<p>That's some text again.</p>
<p class='paragraphtitle'>Example2</p>
<p>That's some other text.</p>
<p>That's some other text again.</p>
<!-- potentially add more paragraphtitles -->

<p class='sectiontitle'>New title</p>
<p>Some non-needed text.</p>

I want to run a template to work on each paragraph section where I wrap the title and its following content in some new tags.

So I have a XSLT1.1/Xpath1 file that selects all p[@class='paragraphtitle'] and inside the template for these, I want to select their following siblings until the next subtitle or sectiontitle.

<xsl:template match="p[@class='paragraphtitle']" mode="create-example-block">
  <example>
    <title>
      <xsl:value-of select="." />
    </title>
    <xsl:apply-templates
      select="//p[@class='sectiontitle' or @class='paragraphtitle']/preceding-sibling::*[preceding-sibling::p[@class='paragraphtitle'][1] = text() and not(self::p[@class='sectiontitle' or @class='paragraphtitle'] or not(self::*[following-sibling::p[@class='sectiontitle']]))]" />
  </example>
</xsl:template>

That does not produce the expected output, in this case I expect:

<example>
  <title>Example1</title>
  <p>That's some text.</p>
  <p>That's some text again.</p>
</example>
<example>
  <title>Example2</title>
  <p>That's some other text.</p>
  <p>That's some other text again.</p>
</example>

Can anybody give me a hint?

1 个答案:

答案 0 :(得分:1)

您可以尝试对模板进行这一小改动 - 寻找所有以下兄弟姐妹,其中当前元素为兄弟姐妹之前的第一个:

    <xsl:template match="p[@class='paragraphtitle']" mode="create-example-block">
        <example>
            <title>
                <xsl:value-of select="." />
            </title>
            <xsl:variable name="thisgid" select="generate-id(.)" />
            <xsl:apply-templates select="following-sibling::p[ not (@class='sectiontitle' or @class='paragraphtitle')]
                            [generate-id( preceding-sibling::p[ @class='paragraphtitle' or  @class='sectiontitle'] [1] ) = $thisgid  ]"/>               
        </example>
    </xsl:template>

使用以下输出:

        <example>
            <title>Example1</title>
            <p>That's some text.</p>
            <p>That's some text again.</p>
        </example>
        <example>
            <title>Example2</title>
            <p>That's some other text.</p>
            <p>That's some other text again.</p>
        </example>