Wednesday 15 January 2014

xml - XSLT: insert elements if they are not present -



xml - XSLT: insert elements if they are not present -

i need update lots of xml files simple configuration. problem have - config element optional in xml files , can have configuration.

so want do:

insert <config/> predefined element's if it's missing insert missing element config tag. if there - leave was.

before:

<root> <config> <!-- optional. can not defined @ --> <element2 attr="c"/> </config> </root>

what want get:

<root> <config> <element1 attr="a"/> <element2 attr="b"/> <!-- not override one, insert if missing --> <element3 attr="c"/> </config> </root>

so thoughts have several templates , apply 1st step if it's not there, , sec step within separate mode. didn't worked out.

upd. i'm using xslt 1.0, i'm guessing switching 2.0 not problem.

predefined elements are:

<element1 attr="a"/> <element2 attr="b"/> <element3 attr="c"/>

imho, should @ opposite end; suppress existing config , install own, using either existing values original config or - if none found - default values.

here's xslt 1.0 implementation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="cfg" match="config/*" use="local-name()" /> <xsl:variable name="default-cfg"> <element1 attr="a"/> <element2 attr="b"/> <element3 attr="c"/> </xsl:variable> <xsl:variable name="root" select="/"/> <!-- identity transform --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="root"> <xsl:copy> <config> <xsl:for-each select="exsl:node-set($default-cfg)/*"> <xsl:call-template name="cfg-element"/> </xsl:for-each> </config> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> <xsl:template match="config"/> <xsl:template name="cfg-element"> <xsl:variable name="name" select="name()"/> <xsl:variable name="default-value" select="@attr"/> <xsl:for-each select="$root"> <xsl:variable name="existing-element" select="key('cfg', $name)"/> <xsl:element name="{$name}"> <xsl:attribute name="attr"> <xsl:choose> <xsl:when test="$existing-element"> <xsl:value-of select="$existing-element/@attr"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$default-value"/> </xsl:otherwise> </xsl:choose> </xsl:attribute> </xsl:element> </xsl:for-each> </xsl:template> </xsl:stylesheet>

xml xslt

No comments:

Post a Comment