问题描述
我需要从以下 xslt 中删除重复值.如果只有它们的所有属性都相等,则两个节点应该相等.我想出的解决方案是查找组件名称的第一次出现(0 个前面的兄弟姐妹).如果没有后续兄弟节点,则直接复制节点.如果有以下兄弟节点,则将包括当前节点在内的所有节点放入一个变量中.使用下面的代码处理变量以查找唯一的出现并在找到时复制节点.问题是使用 函数复制节点似乎不起作用.关于如何解决这个问题的任何建议?
I need to remove duplicate values from the following xslt. Two nodes should be equal if only all their attributes are equal.The solution I've come up with is to look for the first occurrence of a component name(0 preceding siblings). If there are no following siblings then directly the copy the node. If there are following siblings then get all the nodes including the current node in to a variable. Process the variable with the code below to find unique occurences and copy the node when found. The problem is that copying the node with the <xsl:copy-of>
function does not seem to work.Any suggestions on how I could get about this?
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>
推荐答案
疯狂猜测,如果你用
<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
),那么它会变得更复杂:
you might get what you want. If you really want to number result components in their name (e.g. compA1
) then it gets more complicated:
<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>
这篇关于从自定义函数复制节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!