Первое замечание: xsl:for-each-group
- это команда XSLT 2.0, поэтому вам следует убедиться, что вы используете процессор, который может обрабатывать XSLT 2.0
В любом случае, одна из причин, по которой он не работает, заключается в том, что когда вы делаете<xsl:for-each-group select="Source" group-by="name">
, вы находитесь в шаблоне, который соответствует MapTo
.Поскольку выбор будет относиться к этому элементу MapTo
, вы будете искать дочерние элементы с именем Source
, которых нет.
(РЕДАКТИРОВАТЬ: Или, как справедливо указывает Мартин Хоннен в комментарияхшаблон действительно соответствует дочерним элементам MapTo
, а не MapTo
сам по себе, и поэтому не будет ничего совпадать, и поэтому никогда не будет использоваться ....)
Вам действительно следует изменить свой шаблон насоответствует Mappings
вместо ...
<xsl:template match="Mappings">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each-group select="Source" group-by="@name">
Обратите внимание, что если в сгруппированных элементах Source
у вас могут быть элементы MapToType
с разными типами, вам может понадобиться вложенный xsl:for-each-group
внутри этого элемента..
Попробуйте этот XSLT ....
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method ="xml" indent ="yes"/>
<xsl:template match="Mappings">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each-group select="Source" group-by="@name">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each-group select="current-group()/MapToType" group-by="@type">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="current-group()/MapTo" />
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
В качестве альтернативы, если MapToType
всегда будет иметь одинаковые type
для каждого сгруппированного элемента Source
, вы можете упроститьXSLT к этому ..
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method ="xml" indent ="yes"/>
<xsl:template match="Mappings">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each-group select="Source" group-by="@name">
<xsl:copy>
<xsl:apply-templates select="@*" />
<MapToType>
<xsl:apply-templates select="MapToType/@*" />
<xsl:apply-templates select="current-group()/MapToType/MapTo" />
</MapToType>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
РЕДАКТИРОВАТЬ: Если вы используете только XSLT 1.0, то вам нужно использовать технику под названием Muenchian Grouping.Это будет подавляющим, если вы новичок в XSLT, особенно в этом случае, если у вас есть вложенная группировка, которая должна учитывать родительский элемент.
Попробуйте этот XSLT затем:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method ="xml" indent ="yes"/>
<xsl:key name="Sources" match="Source" use="@name" />
<xsl:key name="MapToTypes" match="MapToType" use="concat(../@name, @type)" />
<xsl:template match="Mappings">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each select="Source[generate-id() = generate-id(key('Sources', @name)[1])]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each select="key('Sources', @name)/MapToType[generate-id() = generate-id(key('MapToTypes', concat(../@name, @type))[1])]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="key('MapToTypes', concat(../@name, @type))/MapTo" />
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
См.это в действии на http://xsltfiddle.liberty -development.net / jyRYYhX
Читайте о мюнхенской группировке на http://www.jenitennison.com/xslt/grouping/muenchian.html. Затем прочитайте это снова.И снова ....