Search code examples
xmlxpathxslt-1.0

xpath xslt not returning results


I have the following xml

<?xml version="1.0" encoding="UTF-8"?>
<getCarResponse xmlns="http://cars-collections.azurewebsites.net/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <getCarResult>
        <Rows xmlns="">
            <Car>
                <ID>108625</ID>
                <Car_name>Honda</Car_name>
            </Car>
            <Car>
                <ID>317971</ID>
                <Car_name>Toyota</Car_name>
            </Car>
            <Car>
                <ID>317972</ID>
                <Car_name>Nissan</Car_name>
            </Car>
      </Rows>
   </getCarResult>
</getCarResponse>

I want to return a list of car names as follows but its not returning any results. Whats the correct xpath expression to get the desired result?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:form="http://forms.com/forms"
 xmlns:cars="http://cars-collections.azurewebsites.net/"
 exclude-result-prefixes="form cars">



<xsl:template match="/">
     <form:form-data>
        <form:field>
            <form:name>cars</form:name>
            <form:options>
                <!--Zero or more repetitions:-->
                <xsl:for-each select="//cars:Car">
                    <form:option>
                        <form:label>
                            <xsl:value-of select="//cars:Car_name"/>
                        </form:label>
                        <form:value>
                            <xsl:value-of select="//cars:Car_name"/>
                        </form:value>
                    </form:option>
                </xsl:for-each>
            </form:options>
        </form:field>
    </form:form-data>
</xsl:template>

</xsl:stylesheet>

Solution

  • The elements Car and Car_name are not in the http://cars-collections.azurewebsites.net/ namespace. They are in no-namespace, inherited from their Rows ancestor.

    Try instead:

    <xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:form="http://forms.com/forms"
     xmlns:cars="http://cars-collections.azurewebsites.net/"
     exclude-result-prefixes="cars">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="/cars:getCarResponse">
         <form:form-data>
            <form:field>
                <form:name>cars</form:name>
                <form:options>
                    <!--Zero or more repetitions:-->
                    <xsl:for-each select="cars:getCarResult/Rows/Car">
                        <form:option>
                            <form:label>
                                <xsl:value-of select="Car_name"/>
                            </form:label>
                            <form:value>
                                <xsl:value-of select="Car_name"/>
                            </form:value>
                        </form:option>
                    </xsl:for-each>
                </form:options>
            </form:field>
        </form:form-data>
    </xsl:template>
    
    </xsl:stylesheet>
    

    This also avoids the use of // which is less efficient in xsl:for-each and plainly incorrect in xsl:value-of.