Merge adjacent sibling nodes with XSLT

前端 未结 4 1693
闹比i
闹比i 2021-01-06 10:28

I have a question that caused me a terrible headache. Please help me. The input is:


 

section 1

相关标签:
4条回答
  • 2021-01-06 10:49

    The issue is that your XML isn't structured enough for a simple XSLT solution.

    The different "section"s are not really setup in a way that is easy to extract them. If you have control over the input XML see if you can change it to something like this:

    <body>
     <p class="section"> section 1 
      <p class="code"> some code </p>
      <p class="code"> following code </p>
      <p class="code"> following code </p>
     </p>
     <p class="section"> section 2
      <p class="code"> other code </p>
      <p class="code"> following code </p>
      <p class="code"> following code </p>
     </p>
     <p class="section"> section 3
      <p class="code"> still other code </p>
      <p class="code"> following </p>
      <p class="code"> following </p>
     </p>
    </body>
    

    This will let you define a xsl-template for "section"s in which you can xsl-foreach over the "code" classes.

    0 讨论(0)
  • 2021-01-06 10:59

    Something like this should work:

    <xsl:template match="body">
        <xsl:apply-templates select="p[@class='section']" />
    </xsl:template>
    
    <xsl:template match="p[@class='section']">
        <xsl:copy-of select="."/>
        <pre>
            <xsl:variable name="code" select="following-sibling::p[@class='code']" />
            <xsl:for-each select="following-sibling::p">
                <xsl:variable name="index" select="position()"/>
                <xsl:if test="generate-id(.)=generate-id($code[$index])">
                    <xsl:value-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </pre>
    </xsl:template>
    
    0 讨论(0)
  • 2021-01-06 11:11

    You don't need to rebuild your XML, take a look here: XSLT Grouping Siblings.

    0 讨论(0)
  • With XSLT 2.0 you can use for-each-group group-adjacent as follows:

    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="2.0">
    
      <xsl:output indent="yes"/>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="body">
        <xsl:copy>
          <xsl:for-each-group select="*" group-adjacent="boolean(self::p[@class = 'code'])">
            <xsl:choose>
              <xsl:when test="current-grouping-key()">
                <pre>
                  <xsl:apply-templates select="current-group()/node()"/>
                </pre>
              </xsl:when>
              <xsl:otherwise>
                <xsl:apply-templates select="current-group()"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each-group>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    You can use XSLT 2.0 with Saxon 9 or with AltovaXML tools.

    0 讨论(0)
提交回复
热议问题