I'm beggining to work with XSLT and after exploring some solutions, I think it's a good idea to share my issue with you. Maybe someone can help me with this.
I have a XML input data like this:
<?xml version="1.0" encoding="windows-1252"?>
<DOCUMENT>
<SSDP>
<DP>A</DP>
<DX>B</DX>
<XN>1</XN>
<PP>2</PP>
<CO>3</CO>
<XN>4</XN>
<PP>5</PP>
<XN>6</XN>
<PP>7</PP>
<CO>8</CO>
</SSDP>
<SSDP>
<DP>A</DP>
<DL>B</DL>
<DX>C</DX>
<XN>1</XN>
<PP>2</PP>
<CO>3</CO>
<XN>4</XN>
<PP>5</PP>
</SSDP>
</DOCUMENT>
As you see, there are a set of recursive nodes. Concretly, each "XN" node start a new set of recursive nodes until next "XN" field. (The number of fields between "XN" nodes can be dynamic, as you see in the input XML sample). The challenge is include every set of recursive nodes within a new node "DATA".
The wanted output is the following:
<?xml version="1.0" encoding="windows-1252"?>
<DOCUMENT>
<SSDP>
<DP>A</DP>
<DX>B</DX>
<DATA>
<XN>1</XN>
<PP>2</PP>
<CO>3</CO>
</DATA>
<DATA>
<XN>4</XN>
<PP>5</PP>
</DATA>
<DATA>
<XN>6</XN>
<PP>7</PP>
<CO>8</CO>
</DATA>
</SSDP>
<SSDP>
<DP>A</DP>
<DL>B</DL>
<DX>C</DX>
<DATA>
<XN>1</XN>
<PP>2</PP>
<CO>3</CO>
</DATA>
<DATA>
<XN>4</XN>
<PP>5</PP>
</DATA>
</SSDP>
</DOCUMENT>
As I told before, I'm a beginner with XSLT and I tried to create one for solving this issue, but I'm afraid I haven't already enough knowledges.
My first XSLT version is the following:
<?xml version="1.0" encoding="windows-1252"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="DOCUMENT">
<DOCUMENT>
<xsl:for-each select="SSDP">
<SSDP>
<xsl:for-each select="*">
<!-- First element that define a DATA node -->
<xsl:if test="name(.)='XN'">
<xsl:element name="DATA">
<xsl:copy-of select="."/>
</xsl:element>
</xsl:if>
<!-- List of elements that define a DATA node -->
<xsl:if test="name(.)!='XN' and
name(.)!='PP' and
name(.)!='CO'">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</SSDP>
</xsl:for-each>
</DOCUMENT>
</xsl:template>
</xsl:stylesheet>
But the result is incomplete...
<?xml version="1.0" encoding="UTF-8"?>
<DOCUMENT>
<SSDP>
<DP>A</DP>
<DX>B</DX>
<DATA>
<XN>1</XN>
</DATA>
<DATA>
<XN>4</XN>
</DATA>
<DATA>
<XN>6</XN>
</DATA>
</SSDP>
<SSDP>
<DP>A</DP>
<DL>B</DL>
<DX>C</DX>
<DATA>
<XN>1</XN>
</DATA>
<DATA>
<XN>4</XN>
</DATA>
</SSDP>
</DOCUMENT>
I think after include "DATA" node and hovering over the "XN" node, I need adding the following "PP" or "CO" nodes, using some functions like "following::" or something like that... But I don't know how.
Also I'm afraid that there is a much better way to resolve this issue than I'm thinking.
Thanks in advance!
Also I'm afraid that there is a much better way to resolve this issue than I'm thinking.
I believe there is:
XSLT 2.0
<xsl:stylesheet version="2.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="/DOCUMENT">
<xsl:copy>
<xsl:for-each select="SSDP">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="XN">
<xsl:choose>
<xsl:when test="self::XN">
<DATA>
<xsl:copy-of select="current-group()" />
</DATA>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>