Wrapping several optional XML elements in a new wrapper XML element using XSLT

I have an XML file that looks like this:

<a>
  ......
  <b>
    <c>
      <c1>some text</c1>
    </c>
    <d>
      <d1>some more text</d1>
      <d1>even more text</d1>
    </d>
    <e>
      <e1>some more text</e1>
      <e1>even more text</e1>
    </e>
  </b>
</a>

And I want to wrap the items <d>and <e>in the element <wrapper>, so I can have something like the following:

<a>
  ......
  <b>
    <c>
      <c1>some text</c1>
    </c>
    <wrapper>
      <d>
        <d1>some more text</d1>
        <d1>even more text</d1>
      </d>
      <e>
        <e1>some more text</e1>
        <e1>even more text</e1>
        <e2>even more</e2>
      </e>
    </wrapper>
  </b>
  ......
</a>

One of the problems that I face (besides the fact that I am new to XSLT) is that both <d>, and <e>are optional.

How can i do this?

+3
source share
3 answers

This conversion is :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="b/*[self::d or self::e][1]">
  <wrapper>
    <xsl:apply-templates mode="copy" select=
    ". | following-sibling::*[self::d or self::e]"/>
  </wrapper>
 </xsl:template>

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

 <xsl:template match="b/*[self::d or self::e][position()>1]"/>
</xsl:stylesheet>

when applied to the provided XML document :

<a>   ......   
    <b>
        <c>
            <c1>some text</c1>
        </c>
        <d>
            <d1>some more text</d1>
            <d1>even more text</d1>
        </d>
        <e>
            <e1>some more text</e1>
            <e1>even more text</e1>
        </e>
    </b>
</a>

creates the desired result :

<a>   ......   
    <b>
        <c>
            <c1>some text</c1>
        </c>
        <wrapper>
            <d>
                <d1>some more text</d1>
                <d1>even more text</d1>
            </d>
            <e>
                <e1>some more text</e1>
                <e1>even more text</e1>
            </e>
        </wrapper>
    </b>
</a>

Note : override identity rules +.

+2

Dimitre , , :

<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="*[self::d|self::e][1]">
        <wrapper>
            <xsl:call-template name="group"/>
        </wrapper>
        <xsl:apply-templates select="following-sibling::node()
                                        [not(self::d|self::e)][1]"/>
    </xsl:template>
    <xsl:template match="node()" mode="group" name="group">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]
                                                [self::d|self::e]"
                             mode="group"/>
    </xsl:template>
</xsl:stylesheet>

:

<a>   ......   
    <b>
        <c>
            <c1>some text</c1>
        </c>
        <wrapper>
            <d>
                <d1>some more text</d1>
                <d1>even more text</d1>
            </d>
            <e>
                <e1>some more text</e1>
                <e1>even more text</e1>
            </e>
        </wrapper>
    </b>
</a>

EDIT: .

. . , wrapper.

+2

Can't you just wrap an if test around it?

<wrapper>
    <xsl:if test="/a/b/d">
    <!-- write out the <d> node -->
    </xsl:if>
    <xsl:if test="/a/b/e">
    <!-- write out the <e> node -->
    </xsl:if>
</wrapper>
0
source

Source: https://habr.com/ru/post/1790524/


All Articles