2013-05-09 144 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>