'How to retain specific part of an xml with same element names using XSLT

I have an input xml file and a XSLT script. My input xml :

<?xml version="1.0" ?>
<Lib>
  <book>---</book>            <!-- from here -->
  <regn settr="---" value="---" />
  <regn settr="---" value="---" />
  ...
  <regn settr="---" value="---" />
  <regn settr="---">
    <pointall>
      <author settr="---">
        <point>
          <entry settr="---" value="---" />
        </point>
      </author> 
      <author settr="---">
        <point>
          <entry settr="---" value="---" />
        </point>
      </author>
       ...
       ...
    </pointall>    
  </regn>              <!-- to here -->
  <regn settr="register">
    <card>
      <author settr="register">
        <note>
          <book>---</book>
          <regn settr="---" value="---" />
          <regn settr="---">
            <pointall>
              <author settr="---">
                <point>
                  <some settr="---" value="" />
                </point>
              </author>
            </pointall>
          </regn>
        </note>
      </author>
    </card>
  </regn>
  <regn settr="write">
    <card>
      <author settr="write">
        <note>
          <book>---</book>
          <regn settr="---" value="---" />
            <pointall />
        </note>
      </author>
    </card>
  </regn>
  ...
  ...
  <regn settr="...">
    <card>
      <author settr="...">
        ...
      </author>
    </card>
  </regn>
  <regn settr="---" value="---" />
</Lib>

I am applying XSLT template transformation for the regn elements starting from <regn settr="register"> onwards and then going down. My XSLT looks something like this :

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

<xsl:template match="/Lib">
    <xsl:copy>
     <regn settr="Librarian">
      <xsl:copy-of select="regn/card"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

which applies and transforms my input xml to the below output xml :

<Lib>
  <regn settr="Librarian">
    <card>
      <author settr="register">
        <note>
          <book>---</book>
          <regn settr="---" value="---" />
          <regn settr="---">
            <pointall>
              <author settr="---">
                <point>
                  <some settr="---" value="" />
                </point>
              </author>
            </pointall>
          </regn>
        </note>
      </author>
    </card>
    <card>
      <author settr="write">
        <note>
          <book>---</book>
          <regn settr="---" value="---" />
            <pointall />
        </note>
      </author>
    </card>
  ...
  ...
    <card>
      <author settr="...">
        ...
      </author>
    </card>
  </regn>
  <regn settr="---" value="---" />
</Lib>

i.e. it transforms <regn settr="register">, <regn settr="write">, and the following future <regn settr="..."> elements all as one element which is <regn settr="Librarian">.

But I don't get the content which are after <Lib> and before <regn settr="register">, i.e. the content which I have mentioned in comment line starting "from here" to "to here". I need to retain those content as well. Also register, write, and any other values that may come after that in the future in regn settr element, are dummy values which maynot be fixed for every input file.

Expected Output :

<?xml version="1.0" ?>
<Lib>
<book>---</book>            <!-- from here -->
  <regn settr="---" value="---" />
  <regn settr="---" value="---" />
  ...
  <regn settr="---" value="---" />
  <regn settr="---">
    <pointall>
      <author settr="---">
        <point>
          <entry settr="---" value="---" />
        </point>
      </author> 
      <author settr="---">
        <point>
          <entry settr="---" value="---" />
        </point>
      </author>
       ...
       ...
    </pointall>    
  </regn>              <!-- to here -->
  <regn settr="Librarian">
    <card>
      <author settr="register">
        <note>
          <book>---</book>
          <regn settr="---" value="---" />
          <regn settr="---">
            <pointall>
              <author settr="---">
                <point>
                  <some settr="---" value="" />
                </point>
              </author>
            </pointall>
          </regn>
        </note>
      </author>
    </card>
    <card>
      <author settr="write">
        <note>
          <book>---</book>
          <regn settr="---" value="---" />
            <pointall />
        </note>
      </author>
    </card>
  ...
  ...
    <card>
      <author settr="...">
        ...
      </author>
    </card>
  </regn>
  <regn settr="---" value="---" />
</Lib>

I tried something like this for it but I am not getting desired output from it:

  <xsl:template match="/Lib">
  <xsl:copy-of select="."/>
    <xsl:copy>
        <regn settr="Librarian">
            <xsl:apply-templates select="regn/card"/>
        </regn>
    </xsl:copy>
</xsl:template>

I would appreciate it if anyone could help me out here? Thankyou!



Solution 1:[1]

I think you might simply want the identity transformation plus one change of the attribute e.g.

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

<xsl:template match="regn/@settr[. = 'register']">
    <xsl:attribute name="{name()}">Librarian</xsl:attribute>
</xsl:template>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Martin Honnen