2015-04-22 33 views
0

我需要改變這個輸入XML:XSLT1轉型

<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> 

成輸出XML:

<Log2> 
    <Event Name="David" Target="Computer01|Computer03|Computer04"/> 
    <Event Name="Peter" Target="Computer01|Computer02"/>    
</Log2> 

到目前爲止,我用Muenchian分組的和得到的東西,如:

<Log2>  
    <Event Name="David" Target="Computer01|Computer01|Computer01|Computer03|Computer04"/> 
    <Event Name="Peter" Target="Computer01|Computer02|computer02"/> 
</Log2> 

問題是我無法擺脫我的輸出中的重複機器。

這裏是我的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> 

難道你們幫我使用XSLT 1.0處理器?

+1

請顯示您當前的XSLT樣式表。 –

+0

添加了當前的XSLT,非常感謝! – nereide

回答

1

您實際上需要在此處進行第二組Muenchian分組,因爲您還需要對「用戶」和「主機」的組合進行分組,以獲得每個用戶的不同Host屬性。所以,你需要像這樣一個第二個關鍵:

<xsl:key name="myKey2" match="Connection" use="concat(@User, '|', @Host)"/> 

(注意,管|可以是任何位置,只要你將不會在任何UserHost發生)。

然後你在你的內心xsl:for-each使用像這樣:

<xsl:for-each select="key('myKey', @User)[count(. | key('myKey2', concat(@User, '|', @Host))[1]) = 1]"> 

試試這個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> 

作爲一個側面說明,有沒有真正需要使用xsl:element創建具有靜態元素名字,直接寫出元素。例如

<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> 

另請注意,使用屬性值模板創建Name屬性。

+0

您好,Tim,我剛剛測試過您的XSLT,它的功能就像一個魅力!非常感謝! – nereide