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>

如果@labelKey重复userLogin值组合,我必须@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']"是否可以用概括的语句替换WRand U0002,因为我不确定可能重复的组合值。

提前致谢。苏珊

4

3 回答 3

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>

示例 1 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>

示例 2 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>

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

输出:

<?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>
于 2013-05-09T09:33:48.583 回答
0

如果 sheetFilter 元素的原始顺序不符合,您可以使用基于 MUENCHIAN METHOD 的东西。这也适用于 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>
于 2013-05-09T09:51:12.170 回答
0

仅用于簿记:这里的解决方案可以保持秩序并且无需 for-each 即可工作。

   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>
于 2013-05-09T10:21:12.953 回答