jerol2k3
jerol2k3

Reputation: 35

xslt template transfrom xml from given xml input to expected xml output

Part of xml input which takes time for me to solve the required output.

<contrib-group>
    <contrib contrib-type="editor">
        <name>
            <surname>John</surname>
            <given-names>Cover B.</given-names>
        </name>
        <xref ref-type="aff" rid="aff1">
            <sup>1,2</sup>
        </xref>
    </contrib>
    <contrib contrib-type="author">
        <name>
            <surname>Peter</surname>
            <given-names>Crus J.</given-names>
        </name>
        <xref ref-type="aff" rid="aff1">
            <sup>1,3</sup>
        </xref>
        <name>
            <surname>John</surname>
            <given-names>Cruz K.</given-names>
        </name>
        <xref ref-type="aff" rid="aff1">
            <sup>1</sup>
        </xref>
    </contrib>
</contrib-group>

Part of xml expected output which seems to be simple to capture visually.

<contrib-group>
    <contrib contrib-type="editor">
        <name>
            <surname>John</surname>
            <given-names>Cover B.</given-names>
        </name>
        <xref ref-type="aff" rid="aff1">
            <sup>1,2</sup>
        </xref>
    </contrib>
    <contrib contrib-type="author">
        <name>
            <surname>Peter</surname>
            <given-names>Crus J.</given-names>
        </name>
        <xref ref-type="aff" rid="aff1">
            <sup>1,3</sup>
        </xref>
    </contrib>
    <contrib contrib-type="author">
        <name>
            <surname>John</surname>
            <given-names>Cruz K.</given-names>
        </name>
        <xref ref-type="aff" rid="aff1">
            <sup>1</sup>
        </xref>
    </contrib>
</contrib-group>

Part of current xslt which needs to be corrected to solve the required output.

    <xsl:template match="contrib">    
<xsl:element name="{name()}">                         
    <xsl:for-each select="name">                
        <xsl:element name="{name(parent::*)}">
            <xsl:attribute name="contrib-type">
                <xsl:value-of select="../@contrib-type"/>
            </xsl:attribute>
            <xsl:element name="{name()}">
                <xsl:for-each select="@*">
                    <xsl:attribute name="{name()}">
                        <xsl:value-of select="."/>
                    </xsl:attribute>
                </xsl:for-each>            
            <xsl:apply-templates/>
            </xsl:element>
        </xsl:element>
    </xsl:for-each>
</xsl:element>    
</xsl:template>

It is hard to iterate childs elements inside contrib element which needs to be reproduced as parent tag.

I updated the part of xslt. I need to remove the parent contrib tag and need to add element xref inside populated contrib.

Upvotes: 0

Views: 44

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167516

In XSLT 3 you could use for-each-group group-starting-with plus xsl:copy select="..":

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="contrib-group">
      <xsl:copy>
          <xsl:for-each-group select="contrib/*" group-starting-with="name">
              <xsl:copy select="..">
                  <xsl:apply-templates select="@*, current-group()"/>
              </xsl:copy>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/6pS2B6q

If you are really using Saxon 8 then it won't do XSLT 3 and xsl:copy select but the for-each-group should work (assuming it is a Saxon 8 release that implements XSLT 2, I think most Saxon 8 releases happened during the development of the final XSLT 2 spec, Saxon 8.9 was the first release to implement then final XSLT 2 spec).

For the xsl:copy select=".." in XSLT 3 you could use <xsl:element name="{name(..)}"> in XSLT 2 and you would need to adapt the <xsl:apply-templates select="@*, current-group()"/> to use <xsl:apply-templates select="../@*, current-group()"/>.

Upvotes: 1

Related Questions