2013-05-09 209 views
0

我必須根據父屬性值和子值的組合來更改父節點的屬性。我的輸入XML是如下:根據子值更改父屬性值

<filters> 
<sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
    <userLogin>U0002</userLogin> 
    <containers> 
      <sheetTypeRef name="WorkRequest"/> 
    </containers> 
</sheetFilter> 
<sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
    <userLogin>U0003</userLogin> 
    <containers> 
      <sheetTypeRef name="ARRequest"/> 
    </containers> 
</sheetFilter> 
<sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
    <userLogin>U0002</userLogin> 
    <containers> 
      <sheetTypeRef name="WorkRequest"/> 
    </containers> 
</sheetFilter> 
</filters> 

@labelKeyuserLogin值組合重複的情況下,我有appeneded計數器和所希望的輸出,以取代@labelKey應該是這樣的:

<filters>  
    <sheetFilter filterUsage="table" labelKey="WR1" hidden="false"> 
     <userLogin>U0002</userLogin> 
     <containers> 
      <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
     <userLogin>U0003</userLogin> 
     <containers> 
      <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="WR2" hidden="false"> 
     <userLogin>U0002</userLogin> 
     <containers> 
      <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
</filters> 

我已經寫了下面的XSLT應用轉型:

<xsl:template match="*|@*"> 
    <xsl:copy disable-output-escaping="yes"> 
    <xsl:apply-templates select="@*"/> 
    <xsl:apply-templates select="node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="sheetFilter[@labelKey='WR']"> 
    <xsl:param name="i" select="1" /> 
    <xsl:element name="{ local-name() }" disable-output-escaping="yes"> 

    <xsl:for-each select="userLogin[text()='U0002']" > 
     <xsl:with-param name="i" select="$i +1"/> 
     <xsl:if test="not(../sheetFilter[@labelKey])"> 
     <xsl:apply-templates select="../@*"/> 
     </xsl:if> 

     <xsl:attribute name="labelKey"> 
     <xsl:value-of select="concat('WR', $i)"/> 
     </xsl:attribute> 
    </xsl:for-each> 
    <xsl:apply-templates select="node()"/> 
    </xsl:element> 
</xsl:template> 

但我正在逐漸低於編譯器警告:

Compiler warnings: 
Attribute 'labelKey' outside of element 

和輸出並不一致,在某些節​​點@lableKey本身缺少計數器值被應用到「labelKey」在某些節點。任何人都可以在上述xslt中發現問題嗎?此外,我想知道是否有可能推廣該條件,例如match="sheetFilter[@labelKey='WR']"是否有可能用一個通用語句替換WRU0002,因爲我不確定可能會重複的組合值。

在此先感謝。 蘇珊

回答

0

如果sheetFilter元素的原始順序沒有母校, 你可以使用的東西。這也適用於xlt-1.0。

試試這個:

<?xml version="1.0"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="kSheetFilter" match="sheetFilter " use="concat(@labelKey,'#',userLogin)" /> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="sheetFilter" > 
     <xsl:param name="pos" /> 
     <xsl:param name="copy_cnt"/> 
     <xsl:copy> 
      <xsl:apply-templates select="@* "/> 
      <xsl:if test="$copy_cnt &gt; '1'"> 
       <xsl:attribute name="labelKey" > 
        <xsl:value-of select="concat(@labelKey, $pos)"/> 
       </xsl:attribute> 
      </xsl:if> 
      <xsl:apply-templates select="node()"/> 
     </xsl:copy> 

    </xsl:template> 
    <xsl:template match="/*"> 
     <xsl:copy> 
      <xsl:for-each 
       select="sheetFilter[ generate-id()= 
      generate-id(key('kSheetFilter', concat(@labelKey,'#',userLogin) 
        ) [1])]" > 
       <xsl:variable name="sheets" select="key('kSheetFilter', concat(@labelKey,'#',userLogin))" /> 
       <xsl:for-each select=" $sheets" > 
       <xsl:apply-templates select="."> 
        <xsl:with-param name="pos" select="position()"/> 
        <xsl:with-param name ="copy_cnt" select="count($sheets)" /> 
       </xsl:apply-templates> 
       </xsl:for-each> 
      </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

,這將產生以下輸出:

<filters> 
    <sheetFilter filterUsage="table" labelKey="WR1" hidden="false"> 
       <userLogin>U0002</userLogin> 
       <containers> 
         <sheetTypeRef name="WorkRequest"/> 
       </containers> 
     </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="WR2" hidden="false"> 
       <userLogin>U0002</userLogin> 
       <containers> 
         <sheetTypeRef name="WorkRequest"/> 
       </containers> 
     </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
       <userLogin>U0003</userLogin> 
       <containers> 
         <sheetTypeRef name="ARRequest"/> 
       </containers> 
     </sheetFilter> 
</filters> 
+0

訂單對我來說並不重要。該解決方案效果很好。再次感謝。 – smj100 2013-05-09 10:10:55

0

您的共享XSLT不好。我已創建新的XSLT來獲得所需輸出:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 

    <xsl:template match="filters"> 
    <filters> 
     <xsl:call-template name="abc"> 
     <xsl:with-param name="filter" select="."/> 
     </xsl:call-template> 
    </filters> 
    </xsl:template> 

    <xsl:template name="abc" match="//sheetFilter"> 
    <xsl:param name="filter"/> 
    <xsl:for-each select="$filter/child::*"> 
     <xsl:variable name="labelKey" select="@labelKey"/> 
     <xsl:variable name="userLogin" select="userLogin"/> 
     <sheetFilter filterUsage="{@filterUsage}" 
     labelKey="{if (count(//sheetFilter[@labelKey = $labelKey][userLogin = $userLogin]) gt 1) 
        then concat(@labelKey,sum(count(preceding-sibling::sheetFilter[@labelKey=$labelKey])+1)) 
        else @labelKey 
        }" 
     hidden="{@hidden}"> 
     <xsl:copy-of select="child::*"/> 
     </sheetFilter> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

SAMPLE1 XML:

<filters> 
    <sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
    <userLogin>U0002</userLogin> 
    <containers> 
     <sheetTypeRef name="WorkRequest"/> 
    </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
    <userLogin>U0003</userLogin> 
    <containers> 
     <sheetTypeRef name="ARRequest"/> 
    </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
    <userLogin>U0002</userLogin> 
    <containers> 
     <sheetTypeRef name="WorkRequest"/> 
    </containers> 
    </sheetFilter> 
</filters> 

OUTPUT:

<filters> 
    <sheetFilter filterUsage="table" labelKey="WR1" hidden="false"> 
     <userLogin>U0002</userLogin> 
     <containers> 
     <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
     <userLogin>U0003</userLogin> 
     <containers> 
     <sheetTypeRef name="ARRequest"/> 
     </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="WR2" hidden="false"> 
     <userLogin>U0002</userLogin> 
     <containers> 
     <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
</filters> 

SAMPLE2 XML:

<filters> 
    <sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
    <userLogin>111U0002</userLogin> 
    <containers> 
     <sheetTypeRef name="WorkRequest"/> 
    </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
    <userLogin>U0003</userLogin> 
    <containers> 
     <sheetTypeRef name="ARRequest"/> 
    </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
    <userLogin>U0002</userLogin> 
    <containers> 
     <sheetTypeRef name="WorkRequest"/> 
    </containers> 
    </sheetFilter> 
</filters> 

OUTPUT:

<?xml version="1.0" encoding="UTF-8"?> 
<filters> 
    <sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
     <userLogin>111U0002</userLogin> 
     <containers> 
     <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
     <userLogin>U0003</userLogin> 
     <containers> 
     <sheetTypeRef name="ARRequest"/> 
     </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
     <userLogin>U0002</userLogin> 
     <containers> 
     <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
</filters> 

樣品3 XML:

<filters> 
    <sheetFilter filterUsage="table" labelKey="" hidden="false"> 
    <userLogin>U0002</userLogin> 
    <containers> 
     <sheetTypeRef name="WorkRequest"/> 
    </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
    <userLogin>U0003</userLogin> 
    <containers> 
     <sheetTypeRef name="ARRequest"/> 
    </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
    <userLogin>U0002</userLogin> 
    <containers> 
     <sheetTypeRef name="WorkRequest"/> 
    </containers> 
    </sheetFilter> 
</filters> 

OUTPUT:基於MUENCHIAN方法

<?xml version="1.0" encoding="UTF-8"?> 
<filters> 
    <sheetFilter filterUsage="table" labelKey="" hidden="false"> 
     <userLogin>U0002</userLogin> 
     <containers> 
     <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="AR" hidden="false"> 
     <userLogin>U0003</userLogin> 
     <containers> 
     <sheetTypeRef name="ARRequest"/> 
     </containers> 
    </sheetFilter> 
    <sheetFilter filterUsage="table" labelKey="WR" hidden="false"> 
     <userLogin>U0002</userLogin> 
     <containers> 
     <sheetTypeRef name="WorkRequest"/> 
     </containers> 
    </sheetFilter> 
</filters> 
+0

感謝您的回覆。上面的xslt對1.1有好處嗎?當我嘗試時,我得到了下面的錯誤:錯誤:'null'中的語法錯誤。' 致命錯誤:'無法編譯樣式表' javax.xml.transform.TransformerConfigurationException:無法編譯樣式表 at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:828 ) at com.airbus.sysecc.util.SyseccXSLT.main(SyseccXSLT.java:91) – smj100 2013-05-09 09:51:38

+0

它與2.0。你應該選擇第一個在1.0中 – 2013-05-09 10:20:11

0

只爲記賬:在這裏,這使訂單和做工作,而換每個解決方案。

version="1.0"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="kSheetFilter" match="sheetFilter " use="concat(@labelKey,'#',userLogin)" /> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="sheetFilter" > 
     <xsl:param name="pos" /> 
     <xsl:param name="copy_cnt"/> 
     <xsl:copy> 
      <xsl:apply-templates select="@* "/> 
      <xsl:variable name="sheets" select="key('kSheetFilter',concat(@labelKey,'#',userLogin))" /> 
      <xsl:if test="count($sheets) &gt; '1'"> 
       <xsl:attribute name="labelKey" > 
        <xsl:value-of select="concat(@labelKey, 
            count(preceding-sibling::sheetFilter 
            [ 
            @labelKey = current()/@labelKey and 
            userLogin = current()/userLogin 
            ]) +1 
           )"/> 
       </xsl:attribute> 
      </xsl:if> 
      <xsl:apply-templates select="node()"/> 
     </xsl:copy> 

    </xsl:template> 

</xsl:stylesheet>