Search code examples
xmlxslt-2.0

How to handle target element type list?


I need template for processing specific element types.
I want to provide not one element type but list of element types as parameter. E.g.

<xsl:param name="element_type" select="'hdd;dvd-rom'"/>

How I need to handle such input?

The next is designed template (process only one element type).

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xs"
                version="2.0">

    <xsl:param name="element_type" select="'hdd'"/>
    <xsl:param name="old_value" select="'2016'"/>
    <xsl:param name="new_value" select="'xxxx'"/>


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

    <xsl:template match="*[local-name() eq $element_type]/@name[contains(., $old_value)]">
        <xsl:attribute name="{name()}" select="replace(., $old_value, $new_value)"/>
    </xsl:template>

</xsl:stylesheet>

The below is sample XML.

<?xml version="1.0" encoding="utf-8"?>
<desktop>
    <hdd name="2016-1"/>
    <dvd-rom name="2016-2"/>
    <cd-rom name="2016-3"/>
</desktop>

Solution

  • If you want a sequence (there are no lists in XSLT/XPath) then use select="'hdd', 'dvd-rom'" and then use local-name() = $element_type.

    Depending on how you set the parameter it might be easier to pass in a string with a comma or semicolon or similar delimiter as you do in <xsl:param name="element_type" select="'hdd;dvd-rom'"/> and then use <xsl:variable name="element_types" select="tokenize($element_type, ';')"/> to get a sequence and in the comparison you can finally use local-name() = $element_types.