xml - explanation on duplicate attribute -
i have code on sample xslt , not make part exactly. want understand portion seq_no[/*/*/seq_no[@num = following::seq_no/@num]]
. idea?
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="seq_no[/*/*/seq_no[@num = following::seq_no/@num]]"> <seq_no num="[{count(preceding::seq_no)+1}]{.}"> <xsl:apply-templates/> </seq_no> </xsl:template> </xsl:stylesheet>
and input
<xml> <staff> <seq_no num="0">0</seq_no> <name>xyz</name> </staff> <staff> <seq_no num="1">1</seq_no> <name>xyz</name> </staff> <staff> <seq_no num="1">2</seq_no> <name>abc</name> </staff> <staff> <seq_no num="3">3</seq_no> <name>abc</name> </staff> </xml>
and output
<xml> <staff> <seq_no num="[1]0">0</seq_no> <name>xyz</name> </staff> <staff> <seq_no num="[2]1">1</seq_no> <name>xyz</name> </staff> <staff> <seq_no num="[3]2">2</seq_no> <name>abc</name> </staff> <staff> <seq_no num="[4]3">3</seq_no> <name>abc</name> </staff> </xml>
you trying understand expression seq_no[/*/*/seq_no[@num = following::seq_no/@num]]
. helps break down separate parts. consider following:
/*/*/seq_no
because expression starts /
, absolute path, , match seq_no element in document grand-child of root element of xml. quantify following xpath expression:
[@num = following::seq_no/@num]
so, looking seq_no element num attribute has same value seq_no element follows in document. i.e have duplicated attribute further on in xml.
but fact absolute path here means not relative seq_no matching. so, if there exist duplicate anywhere in document, expression [/*/*/seq_no[@num = following::seq_no/@num]
returns true, , template match seq_no elements in document.
note, not efficient, because evaluating expression each seq_no element in document, though have same value elements. may better once evaluate once variable, , use xsl:choose in template match determines whether need update attribute value.
try xslt, example
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:variable name="duplicate" select="/*/*/seq_no[@num = following::seq_no/@num]"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="seq_no/@num"> <xsl:choose> <xsl:when test="$duplicate"> <xsl:attribute name="num"> <xsl:number count="seq_no" level="any"/> <xsl:value-of select="concat('[', ., ']')"/> </xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:copy/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
note have changed template match num attribute here because part of xml transforming. also, using xsl:number counting too.
Comments
Post a Comment