我需要从以下xslt中删除重复值。如果只有它们的所有属性相等,则两个节点应该相等。
我提出的解决方案是寻找第一次出现的组件名称(0个兄弟姐妹之前)。如果没有兄弟姐妹,则直接复制节点。如果有以下兄弟,则将包括当前节点在内的所有节点放入变量中。使用下面的代码处理变量以查找唯一的出现并在找到时复制节点。问题是使用<xsl:copy-of>
函数复制节点似乎不起作用。
关于如何解决这个问题的任何建议?
XML
<component name="compA">
<group>
<field name="field1" required="Y">
<field name="field2" required="N">
<field name="field3" required="Y">
</group>
</component>
<component name="compB">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field3" required="N">
</group>
</component>
<component name="compA">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field3" required="N">
</group>
</component>
<component name="compC">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field3" required="N">
</group>
</component>
<component name="compA">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field4" required="N">
<field name="field7" required="N">
<field name="field10" required="N">
</group>
</component>
<component name="compA">
<group>
<field name="field1" required="Y">
<field name="field2" required="N">
<field name="field3" required="Y">
</group>
</component>
<component name="compA">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field3" required="N">
</group>
</component>
XSL
<xsl:template match="component">
<xsl:if test="count(preceding-sibling::*[@name=current()/@name])=0">
<xsl:if test="name(//text()/parent::*) != 'component'">
<xsl:choose>
<xsl:when test="count(following-sibling::*[@name=current()/@name])= 0">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:when>
<xsl:when test="count(following-sibling::*[@name=current()/@name]) != 0">
<xsl:variable name="cnt"><xsl:value-of select="count(following-sibling::*[@name=current()/@name]) + 1"/> </xsl:variable>
<xsl:variable name="arr" select="following-sibling::*[@name=current()/@name] | current()"/>
<xsl:value-of select="foo:f($cnt -1, $arr, $cnt)"/>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:if>
</xsl:template>
<xsl:function name="foo:f">
<xsl:param name="i"/>
<xsl:param name="arr"/>
<xsl:param name="cnt"/>
<xsl:copy-of select="$arr[$i]"/>
<xsl:if test="$i != 0">
<xsl:if test="foo:g($i, $cnt - 1, $arr)">
<xsl:comment><xsl:value-of select="$arr[$i]/node()/node()"/></xsl:comment>
<xsl:element name="component">
<xsl:copy-of select="$arr[1]"></xsl:copy-of>
</xsl:element>
</xsl:if>
<xsl:value-of select="foo:f($i -1, $arr, $cnt)"/>
</xsl:if>
</xsl:function>
<xsl:function name="foo:g">
<xsl:param name="i"/>
<xsl:param name="j"/>
<xsl:param name="arr"/>
<xsl:if test="$j>0">
<xsl:value-of select="false()"/>
</xsl:if>
<xsl:if test="$arr[$i]/child::*/child::*/@name != $arr[$j]/child::*/child::*/@name">
<xsl:value-of select="foo:g($i, $j - 1, $arr)"/>
<xsl:copy-of select="$arr[$i]"/>
</xsl:if>
<xsl:if test="$i=$j">
<xsl:value-of select="true()"/>
</xsl:if>
<xsl:if test="$i!=$j">
<xsl:value-of select="false()"/>
</xsl:if>
</xsl:function>
必需输出
<component name="compA1">
<group>
<field name="field1" required="Y">
<field name="field2" required="N">
<field name="field3" required="Y">
</group>
</component>
<component name="compB">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field3" required="N">
</group>
</component>
<component name="compA2">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field3" required="N">
</group>
</component>
<component name="compC">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field3" required="N">
</group>
</component>
<component name="compA3">
<group>
<field name="field1" required="N">
<field name="field2" required="N">
<field name="field4" required="N">
<field name="field7" required="N">
<field name="field10" required="N">
</group>
</component>
答案 0 :(得分:1)
如果您使用
过滤掉任何deep-equal
component
个元素,那么就会猜测
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="component[some $sib in preceding-sibling::component satisfies deep-equal(., $sib)]"/>
</xsl:transform>
你可能得到你想要的东西。如果您真的想在其名称中对结果组件进行编号(例如compA1
),那么它会变得更复杂:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:functx="http://www.functx.com"
exclude-result-prefixes="functx">
<xsl:import href="http://www.xsltfunctions.com/xsl/functx-1.0-nodoc-2007-01.xsl"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="component/@name">
<xsl:variable name="group" select="../../component[@name = current()][not(some $sib in preceding-sibling::component satisfies deep-equal(., $sib))]"/>
<xsl:attribute name="{name()}" select="if ($group[2]) then concat(., functx:index-of-node($group, ..)) else ."/>
</xsl:template>
<xsl:template match="component[some $sib in preceding-sibling::component satisfies deep-equal(., $sib)]"/>
</xsl:transform>