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

Popular posts from this blog

c++ - No viable overloaded operator for references a map -

java - Custom OutputStreamAppender not run: LOGBACK: No context given for <MYAPPENDER> -

java - Cannot secure connection using TLS -