xslt: Copy node if Value like

i want to use xslt to transform a xml to an other. In my case i got a List with many products but i only need one product of them in a new xml file. I got this:

<?xml version="1.0" encoding="UTF-8"?>
<data version="v1.0.0">
    <header>
        <field1>V1</field1>
        <generation_date>
            <date>10.07.2018</date>
            <time>11:19:42</time>
        </generation_date>
    </header>
    <brands />
    <products>
        <product>
            <id>1</id>
            <name>1</name>
            <test1>1</test1>
            <test2>1</test2>
        </product>
        <product>
            <id>2</id>
            <name>2</name>
            <test1>2</test1>
            <test2>2</test2>
        </product>
    </products>
</data>

and i need only products with id 1

<?xml version="1.0" encoding="UTF-8"?>
<data version="v1.0.0">
    <header>
        <field1>V1</field1>
        <generation_date>
            <date>10.07.2018</date>
            <time>11:19:42</time>
        </generation_date>
    </header>
    <brands />
    <products>
        <product>
            <id>1</id>
            <name>1</name>
            <test1>1</test1>
            <test2>1</test2>
        </product>
    </products>
</data>

but iam not able to do this by my own - can someone help me??

best regards, Alex

2 answers

  • answered 2018-07-12 07:20 Aniket V

    You can start with an identity transform template that copies all the input as is and then modify the <product> template to eliminate the ones having id != '1'.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" />
        <xsl:strip-space elements="*" />
    
        <!-- identity transform template to copy input as is to output -->
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()" />
            </xsl:copy>
        </xsl:template>
    
        <!-- remove <product> having id != 1 -->
        <xsl:template match="product[id != '1']" />
    </xsl:stylesheet>
    

    Output

    <data version="v1.0.0">
        <header>
            <field1>V1</field1>
            <generation_date>
                <date>10.07.2018</date>
                <time>11:19:42</time>
            </generation_date>
        </header>
        <brands />
        <products>
            <product>
                <id>1</id>
                <name>1</name>
                <test1>1</test1>
                <test2>1</test2>
            </product>
        </products>
    </data>
    

  • answered 2018-07-12 07:30 Christian Mosz

    The following code copies everything from the input file except multiple product in products. If you want to check for the id you can do it by:

    <xsl:apply-templates select="product[id = '1']"/>
    

    This code only applies products which have a node named id which content is '1'. The template match on @* in my code means its matching on every attribute in a node too.

    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="* | @*">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="products">
        <xsl:copy>
            <xsl:apply-templates select="product[1]"/>
        </xsl:copy>
    </xsl:template>