Here is the complete XSLT 2.0 transformation, which, in accordance with an external parameter, identifies elements that have a specific attribute name and value, and for each of these elements, all attributes that are not white are deleted and other specified attributes are added
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:param name="vFilters"> <filter> <markerAttribute name="root">2.16.840.1.113883.3.51.1.1.6.1</markerAttribute> <whiteListedAttributes> <name>root</name> <name>foo</name> </whiteListedAttributes> <addAtributes flavor="MSK" reason="Demo"/> </filter> </xsl:param> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match= "*[for $cur in ., $m in $vFilters/filter/markerAttribute return $cur/@*[name() eq $m/@name and . eq $m] ]"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:copy-of select= "for $m in $vFilters/filter/markerAttribute return if(current()/@* [name() eq $m/@name and . eq $m ]) then $m/../addAtributes/@* else () "/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match= "@*[for $cur in ., $p in .., $m in $vFilters/filter/markerAttribute return $p/@*[name() eq $m/@name and . eq $m] and not(name($cur) = $m/../whiteListedAttributes/name) ] "/> </xsl:stylesheet>
When this conversion is applied to the following XML document (based on the provided but added one whitelisted attribute):
<root> <childNode> <innerChild root="2.16.840.1.113883.3.51.1.1.6.1" a="b" b="c" foo="bar" type="innerChildness"/> <innerChildSibling/> </childNode> <animals> <cat> <name>bob</name> </cat> </animals> <tree/> <water root="2.16.840.1.113883.3.51.1.1.6.1" z="zed" l="ell" type="liquidLIke"/> </root>
The obtained, correct result is obtained . In the identified elements, all attributes not included in the white list are deleted and two new attributes specified in the filter are added:
<root> <childNode> <innerChild root="2.16.840.1.113883.3.51.1.1.6.1" foo="bar" flavor="MSK" reason="Demo"/> <innerChildSibling/> </childNode> <animals> <cat> <name>bob</name> </cat> </animals> <tree/> <water root="2.16.840.1.113883.3.51.1.1.6.1" flavor="MSK" reason="Demo"/> </root>
Explanation
The external parameter $vFilters may contain one or more filters in the following form:
<filter> <markerAttribute name="root">2.16.840.1.113883.3.51.1.1.6.1</markerAttribute> <whiteListedAttributes> <name>root</name> <name>foo</name> </whiteListedAttributes> <addAtributes flavor="MSK" reason="Demo"/> </filter>
The markerAttribute element indicates the name and value of the identification attribute. In this case, the filter identifies (for) elements that have a root attribute whose value is "2.16.840.1.113883.3.51.1.1.6.1" .
Two whitelisted attribute names are specified in this filter: root and foo .
Two new attributes with the specified values ββmust be added to each identified by this filter element: flavor="MSK" and reason="Demo" .
The external parameter $vFilters can contain many filters, each of which identifies a different "type" of the element and sets a different set of names for white list attributes and new attributes to be added.