How can I wrap a group of adjacent elements using XSLT?

后端 未结 2 1635
一整个雨季
一整个雨季 2020-12-06 18:27

I have some XML with elements, and I\'d like to wrap any consecutive runs with elements. So, source XML would look so

相关标签:
2条回答
  • 2020-12-06 18:37

    This stylesheet:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:strip-space elements="*"/>
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()[1]"/>
            </xsl:copy>
            <xsl:apply-templates select="following-sibling::node()[1]"/>
        </xsl:template>
        <xsl:template match="ListItem">
            <List>
                <xsl:call-template name="ListItem"/>
            </List>
            <xsl:apply-templates select="following-sibling::node()
                                          [not(self::ListItem)][1]"/>
        </xsl:template>
        <xsl:template match="ListItem[preceding-sibling::node()[1]
                                                  /self::ListItem]"
                      name="ListItem">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()[1]"/>
            </xsl:copy>
            <xsl:apply-templates select="following-sibling::node()[1]
                                                     /self::ListItem"/>
        </xsl:template>
    </xsl:stylesheet>
    

    Output:

    <Section>
        <Head>Heading</Head>
        <Para>Blah</Para>
        <List>
            <ListItem>item 1</ListItem>
            <ListItem>item 2</ListItem>
            <ListItem>item 3</ListItem>
            <ListItem>item 4</ListItem>
        </List>
        <Para>Something else</Para>
    </Section>
    

    Edit 3: Using strip-space for what it is.

    0 讨论(0)
  • 2020-12-06 18:47

    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:key name="kFollowing" match="ListItem[preceding-sibling::*[1][self::ListItem]]"
      use="generate-id(preceding-sibling::ListItem
             [not(preceding-sibling::*[1][self::ListItem])][1])"/>
    
     <xsl:template match="node()|@*" name="identity">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="ListItem
             [not(preceding-sibling::*[1][self::ListItem])]">
      <List>
        <xsl:call-template name="identity"/>
        <xsl:apply-templates mode="copy" select="key('kFollowing', generate-id())"/>
      </List>
     </xsl:template>
    
     <xsl:template match="ListItem[preceding-sibling::*[1][self::ListItem]]"/>
    
     <xsl:template match="ListItem" mode="copy">
      <xsl:call-template name="identity"/>
     </xsl:template>
    </xsl:stylesheet>
    

    when applied on the provided XML document:

    <Section>
      <Head>Heading</Head>
      <Para>Blah</Para>
      <ListItem>item 1</ListItem>
      <ListItem>item 2</ListItem>
      <ListItem>item 3</ListItem>
      <ListItem>item 4</ListItem>
      <Para>Something else</Para>
    </Section>
    

    produces the wanted result:

    <Section>
        <Head>Heading</Head>
        <Para>Blah</Para>
        <List>
            <ListItem>item 1</ListItem>
            <ListItem>item 2</ListItem>
            <ListItem>item 3</ListItem>
            <ListItem>item 4</ListItem>
        </List>
        <Para>Something else</Para>
    </Section>
    
    0 讨论(0)
提交回复
热议问题