I want to create a XSD structure from an Excel output using XSLT. But my XSLT does not generate the hierarchical structure, correctly. It has some additional nodes in an element group, if these nodes with same matching parameters are defined in a later group, which has the same level in the hierarchy.
The Excel XML output looks like following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nodes>
<node typeTag="Test" nodeTag="GGG" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
<metaInfo><ID>40</ID><Level>1</Level></metaInfo>
</node>
<node typeTag="Test" nodeTag="BBB" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
<metaInfo><ID>60</ID><Level>2</Level></metaInfo>
</node>
<node typeTag="Test" nodeTag="XXX" minOccurs="0" segmentMaxOccurs="1000000" groupMaxOccurs="">
<metaInfo><ID>80</ID><Level>2</Level></metaInfo>
</node>
<node typeTag="Test" nodeTag="AAA" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
<metaInfo><ID>90</ID><Level>1</Level></metaInfo>
</node>
<node typeTag="Test" nodeTag="WWW" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
<metaInfo><ID>110</ID><Level>1</Level></metaInfo>
</node>
<node typeTag="Test" nodeTag="OOO" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
<metaInfo><ID>130</ID><Level>1</Level></metaInfo>
</node>
<node typeTag="Test" nodeTag="AAA" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
<metaInfo><ID>140</ID><Level>2</Level></metaInfo>
</node>
<node typeTag="Test" nodeTag="WWW" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
<metaInfo><ID>160</ID><Level>2</Level></metaInfo>
</node>
</nodes>
Each node should be an element, whereby @segmentMaxOccurs != 0 will generate leaf elementa and @groupMaxOccurs will generate group elements. The element "Level" defines the hierarchy of the structure (it should be a nested structure) and the element "ID" is an ordered unique identifier.
Based on this input, I would like to get the following XSD structure. In order to just focus on my issue, I stripped out all not relevant items such as "xs:sequence" or "xs:complexType":
<?xml version="1.0" encoding="UTF-8"?>
<xs:element xmlns:xs="http://www.w3.org/2001/XMLSchema" name="Test">
<xs:element name="GGG" minOccurs="0" maxOccurs="1000000" id="40">
<xs:element name="GGG" minOccurs="0" maxOccurs="1" id="40"/>
<xs:element name="BBB" minOccurs="0" maxOccurs="1000000" id="60">
<xs:element name="BBB" minOccurs="0" maxOccurs="1" id="60"/>
<xs:element name="XXX" minOccurs="0" maxOccurs="1000000" id="80"/>
</xs:element>
</xs:element>
<xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="90">
<xs:element name="AAA" minOccurs="0" maxOccurs="1" id="90"/>
</xs:element>
<xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="110">
<xs:element name="WWW" minOccurs="0" maxOccurs="1" id="110"/>
</xs:element>
<xs:element name="OOO" minOccurs="0" maxOccurs="1000000" id="130">
<xs:element name="OOO" minOccurs="0" maxOccurs="1" id="130"/>
<xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="140">
<xs:element name="AAA" minOccurs="0" maxOccurs="1" id="140"/>
</xs:element>
<xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="160">
<xs:element name="WWW" minOccurs="0" maxOccurs="1" id="160"/>
</xs:element>
</xs:element>
</xs:element>
But I just get the following output:
<?xml version="1.0" encoding="UTF-8"?>
<xs:element xmlns:xs="http://www.w3.org/2001/XMLSchema" name="Test">
<xs:element name="GGG" minOccurs="0" maxOccurs="1000000" id="40">
<xs:element name="GGG" minOccurs="0" maxOccurs="1" id="40"/>
<xs:element name="BBB" minOccurs="0" maxOccurs="1000000" id="60">
<xs:element name="BBB" minOccurs="0" maxOccurs="1" id="60"/>
<xs:element name="XXX" minOccurs="0" maxOccurs="1000000" id="80"/>
</xs:element>
<xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="140">
<xs:element name="AAA" minOccurs="0" maxOccurs="1" id="140"/>
</xs:element>
<xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="160">
<xs:element name="WWW" minOccurs="0" maxOccurs="1" id="160"/>
</xs:element>
</xs:element>
<xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="90">
<xs:element name="AAA" minOccurs="0" maxOccurs="1" id="90"/>
</xs:element>
<xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="110">
<xs:element name="WWW" minOccurs="0" maxOccurs="1" id="110"/>
</xs:element>
<xs:element name="OOO" minOccurs="0" maxOccurs="1000000" id="130">
<xs:element name="OOO" minOccurs="0" maxOccurs="1" id="130"/>
<xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="140">
<xs:element name="AAA" minOccurs="0" maxOccurs="1" id="140"/>
</xs:element>
<xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="160">
<xs:element name="WWW" minOccurs="0" maxOccurs="1" id="160"/>
</xs:element>
</xs:element>
</xs:element>
The group "GGG" has the two addtional groups AAA (id = 140) and WWW (id = 160), which should be just underneath the group OOO. Do you have any idea, how just the correct nodes of GGG will be processed until the group AAA (id = 90), which is at the same level like element group "GGG". I don't have idea, how these nodes will be consumed that just belong to element group "GGG".
This is the part of the XSLT, which is relevant for generating the hierarchical structure:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:nestor="http://sap.com/ia" xmlns:ns1="http://www.sap.com/ia" xmlns:functx="http://sap.com/xslt/functions">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="pRootNode" select="'Test'"/>
<xsl:template match="nodes">
<xsl:variable name="vRootNode" select="$pRootNode"/>
<xsl:element name="xs:element">
<xsl:attribute name="name" select="$vRootNode"/>
<xsl:variable name="vLevel" select="0"/>
<xsl:variable name="vNextLevel" select="1"/>
<xsl:variable name="vGroupCounter" select="node[@typeTag = $vRootNode and @groupMaxOccurs != '']"/>
<xsl:apply-templates select="node[@typeTag = $vRootNode and ((@groupMaxOccurs != '' and ./metaInfo/Level = $vNextLevel) or (@groupMaxOccurs = '' and ./metaInfo/Level = $vLevel))]" mode="MessageStructure">
<xsl:with-param name="pRootNode" select="$vRootNode"/>
<xsl:with-param name="pLevel" select="$vLevel"/>
<xsl:with-param name="pGroupCounter" select="$vGroupCounter"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="node[@groupMaxOccurs = '']" mode="MessageStructure">
<xsl:param name="pRootNode"/>
<xsl:param name="pLevel"/>
<xsl:param name="pGroupCounter"/>
<xsl:variable name="vActGroupCounter" select="count(following-sibling::node[@typeTag = $pRootNode and @groupMaxOccurs != ''])"/>
<xsl:if test="./metaInfo/Level = $pLevel and ($vActGroupCounter = $pGroupCounter or $pLevel = 0)">
<xsl:element name="xs:element">
<xsl:attribute name="name" select="@nodeTag"/>
<xsl:attribute name="minOccurs" select="@minOccurs"/>
<xsl:attribute name="maxOccurs" select="@segmentMaxOccurs"/>
<xsl:attribute name="id" select="./metaInfo/ID"/>
</xsl:element>
</xsl:if>
</xsl:template>
<xsl:template match="node[@groupMaxOccurs != '']" mode="MessageStructure">
<xsl:param name="pRootNode"/>
<xsl:param name="pLevel"/>
<xsl:param name="pGroupCounter"/>
<xsl:variable name="vNextLevel" select="$pLevel + 1"/>
<xsl:variable name="vActGroupCounter" select="count(following-sibling::node[@typeTag = $pRootNode and @groupMaxOccurs != ''])"/>
<xsl:variable name="vNextGroupLevel" select="following-sibling::node[@typeTag = $pRootNode and @groupMaxOccurs != ''][1]/metaInfo/Level"/>
<xsl:element name="xs:element">
<xsl:attribute name="name" select="@nodeTag"/>
<xsl:attribute name="minOccurs" select="@minOccurs"/>
<xsl:attribute name="maxOccurs" select="@groupMaxOccurs"/>
<xsl:attribute name="id" select="./metaInfo/ID"/>
<xsl:element name="xs:element">
<xsl:attribute name="name" select="@nodeTag"/>
<xsl:attribute name="minOccurs" select="@minOccurs"/>
<xsl:attribute name="maxOccurs" select="@segmentMaxOccurs"/>
<xsl:attribute name="id" select="./metaInfo/ID"/>
</xsl:element>
<xsl:apply-templates select="following-sibling::node[@typeTag = $pRootNode and ((@groupMaxOccurs != '' and ./metaInfo/Level = $vNextLevel + 1 and ./metaInfo/Level = $vNextGroupLevel) or (@groupMaxOccurs = '' and ./metaInfo/Level = $vNextLevel))]" mode="MessageStructure">
<xsl:with-param name="pRootNode" select="$pRootNode"/>
<xsl:with-param name="pLevel" select="$vNextLevel"/>
<xsl:with-param name="pGroupCounter" select="$vActGroupCounter"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Any support is really appreciated. Many thanks in advance.