xml - XSLT1 Transformation -
i need transform input xml:
<log1> <connection user="peter" host="computer01" port="22"/> <connection user="peter" host="computer02" port="22"/> <connection user="peter" host="computer02" port="80"/> <connection user="david" host="computer01" port="8080"/> <connection user="david" host="computer01" port="8080"/> <connection user="david" host="computer01" port="8080"/> <connection user="david" host="computer03" port="22"/> <connection user="david" host="computer04" port="21"/> </log1>
into output xml:
<log2> <event name="david" target="computer01|computer03|computer04"/> <event name="peter" target="computer01|computer02"/> </log2>
so far, used muenchian grouping , obtained like:
<log2> <event name="david" target="computer01|computer01|computer01|computer03|computer04"/> <event name="peter" target="computer01|computer02|computer02"/> </log2>
the problem cannot rid of duplicate machines in output.
here xslt:
<xsl:key name="mykey" match="connection" use="@user"/> <xsl:variable name="separator" select="'|'"/> <xsl:template match="log1"> <xsl:element name="log2"> <xsl:for-each select="connection[count(. | key('mykey', @user)[1]) = 1]"> <xsl:sort select="@user" /> <xsl:element name="event"> <xsl:attribute name="name"> <xsl:value-of select="@user" /> </xsl:attribute> <xsl:attribute name="target"> <xsl:for-each select="key('mykey', @user)"> <xsl:sort select="@host" /> <xsl:value-of select="@host" /> <xsl:if test="position() != last()"> <xsl:value-of select="$separator" /> </xsl:if> </xsl:for-each> </xsl:attribute> </xsl:element> </xsl:for-each> </xsl:element> </xsl:template>
could guys me using xslt 1.0 processor?
you need second set of muenchian grouping here, because need group on combination of "user" , "host" distinct host
attribute each user. so, need second key so:
<xsl:key name="mykey2" match="connection" use="concat(@user, '|', @host)"/>
(note pipe |
here, long doesn't occur in either user
or host
).
and use in inner xsl:for-each
so:
<xsl:for-each select="key('mykey', @user)[count(. | key('mykey2', concat(@user, '|', @host))[1]) = 1]">
try 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="mykey" match="connection" use="@user"/> <xsl:key name="mykey2" match="connection" use="concat(@user, '|', @host)"/> <xsl:variable name="separator" select="'|'"/> <xsl:template match="log1"> <xsl:element name="log2"> <xsl:for-each select="connection[count(. | key('mykey', @user)[1]) = 1]"> <xsl:sort select="@user" /> <xsl:element name="event"> <xsl:attribute name="name"> <xsl:value-of select="@user" /> </xsl:attribute> <xsl:attribute name="target"> <xsl:for-each select="key('mykey', @user)[count(. | key('mykey2', concat(@user, '|', @host))[1]) = 1]"> <xsl:sort select="@host" /> <xsl:value-of select="@host" /> <xsl:if test="position() != last()"> <xsl:value-of select="$separator" /> </xsl:if> </xsl:for-each> </xsl:attribute> </xsl:element> </xsl:for-each> </xsl:element> </xsl:template> </xsl:stylesheet>
as side note, there no real need use xsl:element
create elements static names, write element out directly. example
<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="mykey" match="connection" use="@user"/> <xsl:key name="mykey2" match="connection" use="concat(@user, '|', @host)"/> <xsl:variable name="separator" select="'|'"/> <xsl:template match="log1"> <log2> <xsl:for-each select="connection[count(. | key('mykey', @user)[1]) = 1]"> <xsl:sort select="@user" /> <event name="{@user}"> <xsl:attribute name="target"> <xsl:for-each select="key('mykey', @user)[count(. | key('mykey2', concat(@user, '|', @host))[1]) = 1]"> <xsl:sort select="@host" /> <xsl:value-of select="@host" /> <xsl:if test="position() != last()"> <xsl:value-of select="$separator" /> </xsl:if> </xsl:for-each> </xsl:attribute> </event> </xsl:for-each> </log2> </xsl:template> </xsl:stylesheet>
also note use of attribute value templates in creating name
attribute.
Comments
Post a Comment