xslt - Copying a node from a custom function -
i need remove duplicate values following xslt. 2 nodes should equal if attributes equal. solution i've come first occurrence of component name(0 preceding siblings). if there no following siblings directly copy node. if there following siblings nodes including current node in variable. process variable code below find unique occurences , copy node when found. problem copying node <xsl:copy-of>
function not seem work. suggestions on how 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>
required output
<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>
wild guess, if filter out deep-equal
component
elements with
<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>
you might want. if want number result components in name (e.g. compa1
) 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]) 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>
Comments
Post a Comment