我必须根据父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>
如果@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']"
是否可以用一般化语句替换WR
和U0002
,因为我不确定组合值可能会重复。
提前致谢。 苏珊
答案 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 > '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) > '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>