Reputation: 35
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
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