我搜索了所有xslt映射问题,但还没有找到解决我的具体案例的方法。
所以,假设这是我的源XML:
<Data>
<A val='1'>
<CC>1234</CC>
</A>
<A val='2'>
<CC>1234</CC>
<CC>5678</CC>
</A>
<A val='3'>
<CC>1234</CC>
</A>
<B val='1'>
<CC>5678</CC>
</B>
<B val='2'>
<CC>1234</CC>
<CC>9012</CC>
</B>
</Data>
我想要的结果如下:
<Data>
<A val='1'>
<CC>-1</CC>
</A>
<A val='2'>
<CC>-1</CC>
<CC>-2</CC>
</A>
<A val='3'>
<CC>-1</CC>
</A>
<B val='1'>
<CC>-2</CC>
</B>
<B val='2'>
<CC>-1</CC>
<CC>-3</CC>
</B>
</Data>
如果我用某种编程语言对它进行编码,我会首先将所有CC值放入一个集合/集合中,然后当我知道所有可能的CC值时,我会迭代整个集合并替换XML中的值使用在循环内减少的计数器。但我不知道如何在XSLT中做到这一点...... 所以在上面的例子中,我有CC值1234,5678和9012。 当迭代这些值时,所有具有1234的CC值应该变为-1,5678 ==&gt; -2和9012 ==&gt; -3 ,无论CC是在A还是B 。如果5678映射到-1,9012到-2和1234到-3也可以,但所有出现的1234必须更改为-3然后依此类推。 谢谢你的帮助!
答案 0 :(得分:1)
假设您可以使用XSLT 2.0,您可以使用distinct-values
获取CC
的不同值,然后对于每个CC
,您可以使用index-of
来查找它在不同列表中的位置,并使用它来输出您想要的数字。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="distinctCC" select="distinct-values(//CC)" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CC">
<xsl:copy>
<xsl:value-of select="0 - index-of($distinctCC, text())" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如果你只能使用XSLT 1.0,那么你可以回到使用Muenchian Grouping来获得不同的值,尽管找到索引的工作也更多了。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="cc" match="CC" use="." />
<xsl:variable name="distinctCC" select="//CC[generate-id() = generate-id(key('cc', .)[1])]" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CC">
<xsl:copy>
<xsl:variable name="current" select="text()" />
<xsl:variable name="pos">
<xsl:for-each select="$distinctCC">
<xsl:if test="$current = ."><xsl:value-of select="position()" /></xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="0 - $pos" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
你可以创建一个&#34;地图&#34;将所有distinct-values放在变量中,例如:
<xsl:variable name="CCcoll">
<xsl:for-each select="distinct-values(//CC)">
<CC><xsl:value-of select="."/></CC>
</xsl:for-each>
</xsl:variable>
为CC
个节点添加标识模板和模板覆盖:
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CC">
<xsl:variable name="curr_CC" select="."/>
<xsl:copy>
<!-- here, you are matching the
current value to the "map"
and getting it's position -->
<xsl:value-of select="concat('-', $CCcoll/CC[.=$curr_CC]/count(preceding-sibling::*) + 1)"/>
</xsl:copy>
</xsl:template>
整个样式表如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:variable name="CCcoll">
<xsl:for-each select="distinct-values(//CC)">
<CC><xsl:value-of select="."/></CC>
</xsl:for-each>
</xsl:variable>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CC">
<xsl:variable name="curr_CC" select="."/>
<xsl:copy>
<xsl:value-of select="concat('-', $CCcoll/CC[.=$curr_CC]/count(preceding-sibling::*) + 1)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>