根据子值更改父属性值

时间:2013-05-09 07:17:00

标签: xslt

我必须根据父attirbute值和子值的组合更改父节点的属性。我输入的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值组合重复,我必须用附加的计数器替换@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

输出不一致,在某些节​​点中,计数器值应用于'labelKey',在某些节​​点中,@lableKey本身丢失。任何人都可以在上面的xslt中找出错误吗?另外我想知道是否可以概括条件,例如match="sheetFilter[@labelKey='WR']"是否可以用一般化语句替换WRU0002,因为我不确定组合值可能会重复。

提前致谢。 苏珊

3 个答案:

答案 0 :(得分: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>

输出:

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

输出:

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

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

输出:

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

答案 1 :(得分:0)

如果sheetFilter元素的原始顺序不匹配, 你可以使用基于MUENCHIAN方法的东西。这也适用于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>

答案 2 :(得分: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>