Guillaume D.
Guillaume D.

Reputation: 33

XSLT parameters from C# (XML to XML)

I need to transform an XML file to another XML filtered. I want to use XSLT/C# to do this operation. My source code in C# will execute the XSLT file with a list of parameter (I'm using XslCompiledTransform class).

My question is : how in XSLT language I can parse all parameters transmited from the C# to filter the output XML file.

Example : a list of car

 <cars>
    <car brand="Audi" model="A4/>
    <car brand="Audi" model="A6/>
    <car brand="Audi" model="A7/>
    <car brand="Volvo" model="V40" />
    <car brand="Volvo" model="V60" />
    <car brand="Honda" model="Civic" />
    <car brand="Mercedes" model="Class E" />
 </cars>

a simple XSLT with brandsSelect parameter

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">
     <xsl:param name="brandsSelect"></xsl:param>
     <xsl:template match="@* | node()">
         <xsl:copy>
             <xsl:apply-templates select="@* | node()"/>
         </xsl:copy>
     </xsl:template>        
 </xsl:stylesheet>

In my C# source code, I populate my variable : brandsSelect = Volvo, Honda

Expected result :

 <cars> 
    <car brand="Volvo" model="V40" />
    <car brand="Volvo" model="V60" />
    <car brand="Honda" model="Civic" /> 
 </cars>

Thanks for your help !

Upvotes: 3

Views: 165

Answers (1)

Tim C
Tim C

Reputation: 70598

What you could do (in XSLT 1.0 which is what XSLTCompiledTransform implements) is to do a string test to see if the parameter "contains" the brand attribute:

<xsl:template match="cars">
    <xsl:copy>
        <xsl:apply-templates select="car[contains($brandsSelect, @brand)]" />
    </xsl:copy>
</xsl:template>

However, this will fail if one brand happens to be a substring of another (For example, if "Laudi" was brand as well as "Audi"

So, to make it robust, try this XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:param name="brandsSelect">Volvo,Honda</xsl:param>

    <xsl:variable name="brandMatcher" select="concat(',', $brandsSelect, ',')" />

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>     

    <xsl:template match="cars">
        <xsl:copy>
            <xsl:apply-templates select="car[contains($brandMatcher, concat(',', @brand, ','))]" />
        </xsl:copy>
    </xsl:template>
 </xsl:stylesheet>

It is important to note, the value of the brandsSelect should not contain any spaces between the brands, only commas.

Upvotes: 3

Related Questions