XSLT 使用特定级别标准从平面结构创建层次结构
XSLT Create a hierarchical structure from a flat structure by using certain level criteria
我想使用 XSLT 从 Excel 输出创建一个 XSD 结构。但是我的 XSLT 没有正确地生成层次结构。它在一个元素组中有一些额外的节点,如果这些具有相同匹配参数的节点在后面的组中定义,该组在层次结构中具有相同的级别。
Excel XML 输出如下所示:
<?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>
每个节点都应该是一个元素,@segmentMaxOccurs != 0 将生成叶元素,@groupMaxOccurs 将生成组元素。元素"Level"定义了结构的层级(应该是嵌套结构),元素"ID"是有序的唯一标识符。
基于此输入,我想得到以下 XSD 结构。为了只关注我的问题,我删除了所有不相关的项目,例如 "xs:sequence" 或 "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>
但我只得到以下输出:
<?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>
组 "GGG" 有两个附加组 AAA (id = 140) 和 WWW (id = 160),它们应该就在组 OOO 的下面。你知道吗,如何处理 GGG 的正确节点,直到组 AAA (id = 90),它与元素组 "GGG" 处于同一级别。我不知道如何使用这些仅属于元素组 "GGG".
的节点
这是 XSLT 的一部分,与生成层次结构有关:
<?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>
非常感谢您的支持。非常感谢。
这里有一个使用递归函数的建议:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="mf">
<xsl:output indent="yes"/>
<xsl:function name="mf:group" as="element()*">
<xsl:param name="nodes" as="element(node)*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$nodes" group-starting-with="node[metaInfo/Level = $level and @groupMaxOccurs != '']">
<xs:element name="{@nodeTag}" minOccurs="{@minOccurs}" maxOccurs="{@groupMaxOccurs}" id="{metaInfo/ID}">
<xs:element name="{@nodeTag}" minOccurs="0" maxOccurs="1" id="{metaInfo/ID}"/>
<xsl:choose>
<xsl:when test="(current-group() except .)/metaInfo/Level = $level + 1">
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group() except ."/>
</xsl:otherwise>
</xsl:choose>
</xs:element>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="nodes">
<xs:schema>
<xsl:sequence select="mf:group(node, 1)"/>
</xs:schema>
</xsl:template>
<xsl:template match="node">
<xs:element name="{@nodeTag}" minOccurs="0" maxOccurs="{@segmentMaxOccurs}" id="{metaInfo/ID}"/>
</xsl:template>
</xsl:transform>
您将需要进行更多级别的测试或提供一些嵌套更深的输入样本,以便我们进行测试。
让我建议一种创建嵌套层次结构的不同方法。为了演示,我将使用以下最小化输入:
XML
<nodes>
<node nodeTag="A">
<metaInfo>
<Level>1</Level>
</metaInfo>
</node>
<node nodeTag="Ab">
<metaInfo>
<Level>2</Level>
</metaInfo>
</node>
<node nodeTag="Ab1">
<metaInfo>
<Level>3</Level>
</metaInfo>
</node>
<node nodeTag="Ab2">
<metaInfo>
<Level>3</Level>
</metaInfo>
</node>
<node nodeTag="Ac">
<metaInfo>
<Level>2</Level>
</metaInfo>
</node>
<node nodeTag="B">
<metaInfo>
<Level>1</Level>
</metaInfo>
</node>
<node nodeTag="C">
<metaInfo>
<Level>1</Level>
</metaInfo>
</node>
<node nodeTag="D">
<metaInfo>
<Level>1</Level>
</metaInfo>
</node>
<node nodeTag="Da">
<metaInfo>
<Level>2</Level>
</metaInfo>
</node>
<node nodeTag="Db">
<metaInfo>
<Level>2</Level>
</metaInfo>
</node>
</nodes>
应用以下样式表:
XSLT
<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:key name="child-by-parent"
match="node"
use="generate-id(preceding-sibling::node[metaInfo/Level=current()/metaInfo/Level - 1][1])" />
<xsl:template match="nodes">
<root>
<xsl:apply-templates select="node[metaInfo/Level=1]"/>
</root>
</xsl:template>
<xsl:template match="node">
<element name="{@nodeTag}">
<xsl:apply-templates select="key('child-by-parent', generate-id())"/>
</element>
</xsl:template>
</xsl:stylesheet>
将 return:
结果
<?xml version="1.0" encoding="UTF-8"?>
<root>
<element name="A">
<element name="Ab">
<element name="Ab1"/>
<element name="Ab2"/>
</element>
<element name="Ac"/>
</element>
<element name="B"/>
<element name="C"/>
<element name="D">
<element name="Da"/>
<element name="Db"/>
</element>
</root>
这对 任何 个级别递归工作。
我想使用 XSLT 从 Excel 输出创建一个 XSD 结构。但是我的 XSLT 没有正确地生成层次结构。它在一个元素组中有一些额外的节点,如果这些具有相同匹配参数的节点在后面的组中定义,该组在层次结构中具有相同的级别。
Excel XML 输出如下所示:
<?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>
每个节点都应该是一个元素,@segmentMaxOccurs != 0 将生成叶元素,@groupMaxOccurs 将生成组元素。元素"Level"定义了结构的层级(应该是嵌套结构),元素"ID"是有序的唯一标识符。
基于此输入,我想得到以下 XSD 结构。为了只关注我的问题,我删除了所有不相关的项目,例如 "xs:sequence" 或 "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>
但我只得到以下输出:
<?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>
组 "GGG" 有两个附加组 AAA (id = 140) 和 WWW (id = 160),它们应该就在组 OOO 的下面。你知道吗,如何处理 GGG 的正确节点,直到组 AAA (id = 90),它与元素组 "GGG" 处于同一级别。我不知道如何使用这些仅属于元素组 "GGG".
的节点这是 XSLT 的一部分,与生成层次结构有关:
<?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>
非常感谢您的支持。非常感谢。
这里有一个使用递归函数的建议:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="mf">
<xsl:output indent="yes"/>
<xsl:function name="mf:group" as="element()*">
<xsl:param name="nodes" as="element(node)*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$nodes" group-starting-with="node[metaInfo/Level = $level and @groupMaxOccurs != '']">
<xs:element name="{@nodeTag}" minOccurs="{@minOccurs}" maxOccurs="{@groupMaxOccurs}" id="{metaInfo/ID}">
<xs:element name="{@nodeTag}" minOccurs="0" maxOccurs="1" id="{metaInfo/ID}"/>
<xsl:choose>
<xsl:when test="(current-group() except .)/metaInfo/Level = $level + 1">
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group() except ."/>
</xsl:otherwise>
</xsl:choose>
</xs:element>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="nodes">
<xs:schema>
<xsl:sequence select="mf:group(node, 1)"/>
</xs:schema>
</xsl:template>
<xsl:template match="node">
<xs:element name="{@nodeTag}" minOccurs="0" maxOccurs="{@segmentMaxOccurs}" id="{metaInfo/ID}"/>
</xsl:template>
</xsl:transform>
您将需要进行更多级别的测试或提供一些嵌套更深的输入样本,以便我们进行测试。
让我建议一种创建嵌套层次结构的不同方法。为了演示,我将使用以下最小化输入:
XML
<nodes>
<node nodeTag="A">
<metaInfo>
<Level>1</Level>
</metaInfo>
</node>
<node nodeTag="Ab">
<metaInfo>
<Level>2</Level>
</metaInfo>
</node>
<node nodeTag="Ab1">
<metaInfo>
<Level>3</Level>
</metaInfo>
</node>
<node nodeTag="Ab2">
<metaInfo>
<Level>3</Level>
</metaInfo>
</node>
<node nodeTag="Ac">
<metaInfo>
<Level>2</Level>
</metaInfo>
</node>
<node nodeTag="B">
<metaInfo>
<Level>1</Level>
</metaInfo>
</node>
<node nodeTag="C">
<metaInfo>
<Level>1</Level>
</metaInfo>
</node>
<node nodeTag="D">
<metaInfo>
<Level>1</Level>
</metaInfo>
</node>
<node nodeTag="Da">
<metaInfo>
<Level>2</Level>
</metaInfo>
</node>
<node nodeTag="Db">
<metaInfo>
<Level>2</Level>
</metaInfo>
</node>
</nodes>
应用以下样式表:
XSLT
<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:key name="child-by-parent"
match="node"
use="generate-id(preceding-sibling::node[metaInfo/Level=current()/metaInfo/Level - 1][1])" />
<xsl:template match="nodes">
<root>
<xsl:apply-templates select="node[metaInfo/Level=1]"/>
</root>
</xsl:template>
<xsl:template match="node">
<element name="{@nodeTag}">
<xsl:apply-templates select="key('child-by-parent', generate-id())"/>
</element>
</xsl:template>
</xsl:stylesheet>
将 return:
结果
<?xml version="1.0" encoding="UTF-8"?>
<root>
<element name="A">
<element name="Ab">
<element name="Ab1"/>
<element name="Ab2"/>
</element>
<element name="Ac"/>
</element>
<element name="B"/>
<element name="C"/>
<element name="D">
<element name="Da"/>
<element name="Db"/>
</element>
</root>
这对 任何 个级别递归工作。