I am new to xslt. I want to display only matched item(s) from xml list. using xslt transformation.
in this case I only want to display attribute with name of "one" and "two"
Thanks in advance.
xml code:
<myparent>
<mychild>
<mygrndchild name="a" parent="1" >
<attribute name="one" value="1"/>
<attribute name="two" value="1"/>
<attribute name="three" value="1"/>
<attribute name="four" value="0"/>
</mygrndchild>
<mygrndchild name="b" parent="1" >
<attribute name="one2" value="2"/>
<attribute name="two2" value="3"/>
<attribute name="three2" value="4"/>
<attribute name="four2" value="5"/>
</mygrndchild>
</mychild>
</myparent>
xslt code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<!--suppresses attribute in list-->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node() "/>
</xsl:copy>
</xsl:template>
<xsl:template match="/parent">
<xsl:copy>
<xsl:apply-templates select="child"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/child">
<xsl:copy>
<xsl:apply-templates select="grandchild"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/grandchild">
<xsl:copy>
<xsl:apply-templates select="attribute"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/attribute">
<xsl:copy>
<xsl:apply-templates select="@*[. = 'one']"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/attribute">
<xsl:copy>
<xsl:apply-templates select="@*[. = 'two']"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
this code outputs xml as is.
expected results:
<myparent>
<mychild>
<mygrndchild name="a" parent="1" >
<attribute name="one" value="1"/>
</mygrndchild>
<mygrndchild name="a" parent="1" >
<attribute name="two" value="1"/>
</mygrndchild>
</mychild>
</myparent>
I appreciate your help in advance. this is for me learn some xml transformation.
I suspect you want something like
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:param name="att-list" as="xs:string*" select="'one', 'two'"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="attribute[not(@name = $att-list)]"/>
</xsl:stylesheet>
Online fiddle using Saxon HE 12.
If you are really using an XSLT 2 processor replace the xsl:mode
declaration with the identity transformation template (the first one in your posted code).
Or based on the wanted result, assuming XSLT 3, you could use
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:output indent="yes"/>
<xsl:param name="att-list" as="xs:string*" select="'one', 'two'"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="mychild">
<xsl:copy>
<xsl:copy-of select="snapshot(.//attribute[@name = $att-list])/ancestor::mygrndchild"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>