I.Вот очень короткое и простое решение XSLT 2.0 :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each-group select="//*"
group-by="string-join((name(), @*/name()), '|')">
<xsl:sort select="name()"/>
<p>
Element <b><xsl:sequence select="name()"/></b>
has attributes: <xsl:value-of select="@*/name()" separator=", "/>
</p>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к предоставленному документу XML :
<catalog subnodes="2">
<cities country="England">
<city name="London" region="London" population="10000" />
<city name="New South Wales" region="Wales" population="800000" />
</cities>
<articles country="USA">
<article name="My lovely country" src="art1.txt" />
<article name="Places to visit" src="art2.txt" />
<article name="Article 3" src="art3.txt" />
</articles>
<books>
<book title="Warhammer">
<article name="My lovely country" src="art1.txt" />
</book>
<book title="We fought for truth">
<article name="My lovely country" src="art1.txt" />
</book>
</books>
<scientifics atr = " ">
<book title="Warhammer">
<article name="My lovely country" src="art1.txt" />
</book>
</scientifics>
</catalog>
Требуемый, правильный результат выдается :
<p>
Element <b>article</b>
has attributes: name, src</p>
<p>
Element <b>articles</b>
has attributes: country</p>
<p>
Element <b>book</b>
has attributes: title</p>
<p>
Element <b>books</b>
has attributes: </p>
<p>
Element <b>catalog</b>
has attributes: subnodes</p>
<p>
Element <b>cities</b>
has attributes: country</p>
<p>
Element <b>city</b>
has attributes: name, region, population</p>
<p>
Element <b>scientifics</b>
has attributes: atr</p>
и отображается в браузере как :
Элемент артикул имеет атрибуты: имя, источник
элемент статьи имеет атрибуты: страна
элемент книга имеет атрибуты: название
элемент books имеет атрибуты:
Элемент каталог имеет атрибуты: подузлы
Элемент городов имеет атрибуты: страна
Элемент город имеет атрибуты: имя, регион, население
Элемент scientifics имеет атрибуты: atr
II.Решение XSLT 1.0 (двухпроходное):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kElByNameandAttrs" match="*"
use="concat(name(), '|', @_____attribs)"/>
<xsl:variable name="vrtfPass1">
<xsl:apply-templates/>
</xsl:variable>
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="_____attribs">
<xsl:for-each select="@*">
<xsl:sort select="name()"/>
<xsl:value-of select="concat(name(), ' ')"/>
</xsl:for-each>
</xsl:attribute>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates mode="pass2" select=
"ext:node-set($vrtfPass1)//*
[generate-id()
=
generate-id(key('kElByNameandAttrs',
concat(name(),
'|',
@_____attribs)
)
[1])
]"
>
<xsl:sort select="name()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*" mode="pass2">
<p>
Element <b><xsl:value-of select="name()"/></b>
has attributes: <xsl:value-of select="@_____attribs"/></p>
</xsl:template>
</xsl:stylesheet>
когда это преобразование XSLT 1.0 применяется к тому же XML-документу (см. Выше), снова получается требуемый, правильный результат :
<p>
Element <b>article</b>
has attributes: name src </p>
<p>
Element <b>articles</b>
has attributes: country </p>
<p>
Element <b>book</b>
has attributes: title </p>
<p>
Element <b>books</b>
has attributes: </p>
<p>
Element <b>catalog</b>
has attributes: subnodes </p>
<p>
Element <b>cities</b>
has attributes: country </p>
<p>
Element <b>city</b>
has attributes: name population region </p>
<p>
Element <b>scientifics</b>
has attributes: atr </p>