Namespace Stopping XSLT Working

2019-01-26 21:57发布

问题:

I have got an XSLT that looks like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="month">
        <xsl:param name="month"/>
        <month>
            <xsl:choose>
                <xsl:when test="$month">
                    <xsl:value-of select="$month"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates/>
                </xsl:otherwise>
            </xsl:choose>
        </month>
    </xsl:template>

    <xsl:template name="splitMonths">
        <xsl:param name="months"/>
        <xsl:variable name="firstMonth" select="substring-before($months,',')"/>
        <xsl:variable name="month">
            <xsl:choose>
                <xsl:when test="$firstMonth">
                    <xsl:value-of select="$firstMonth"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$months"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="otherMonths" select="substring-after($months,',')"/>
        <xsl:if test="$month">
            <xsl:apply-templates>
                <xsl:with-param name="month" select="$month"/>
            </xsl:apply-templates>
        </xsl:if>
        <xsl:if test="$otherMonths">
            <xsl:call-template name="splitMonths">
                <xsl:with-param name="months" select="$otherMonths"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="payload">
        <payload>
            <xsl:call-template name="splitMonths">
                <xsl:with-param name="months" select="sets/month"/>
            </xsl:call-template>
        </payload>
    </xsl:template>

</xsl:stylesheet>

This is the input:

<?xml version="1.0" encoding="UTF8"?>
 <Response xmlns="http://www.castiron.com/response">
    <code>0</code>
    <message>Success</message>
     <payload>
         <sets>
            <month>AUG,SEP,OCT,NOV,DEC,JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC,JAN</month>
            <season>Season11</season>
            <productId>11111</productId>
        </sets>
    </payload>
</Response>

Because of the name space in the <Response xmlns="http://www.castiron.com/response"> tags this is causing the whole XSLT too fail. Would it be possible to illiminate the namespace so that the XSLT will work. If you remove the namespace and run the XSLT it works perfectly!

回答1:

Define namesapce in XSLT, i.e.:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:r="http://www.castiron.com/response" exclude-result-prefixes="r">

    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="r:month">
        <xsl:param name="month"/>
        <month xmlns="http://www.castiron.com/response">
            <xsl:choose>
                <xsl:when test="$month">
                    <xsl:value-of select="$month"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates/>
                </xsl:otherwise>
            </xsl:choose>
        </month>
    </xsl:template>

    <xsl:template name="splitMonths">
        <xsl:param name="months"/>
        <xsl:variable name="firstMonth" select="substring-before($months,',')"/>
        <xsl:variable name="month">
            <xsl:choose>
                <xsl:when test="$firstMonth">
                    <xsl:value-of select="$firstMonth"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$months"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="otherMonths" select="substring-after($months,',')"/>
        <xsl:if test="$month">
            <xsl:apply-templates>
                <xsl:with-param name="month" select="$month"/>
            </xsl:apply-templates>
        </xsl:if>
        <xsl:if test="$otherMonths">
            <xsl:call-template name="splitMonths">
                <xsl:with-param name="months" select="$otherMonths"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="r:payload">
        <payload xmlns="http://www.castiron.com/response">
            <xsl:call-template name="splitMonths">
                <xsl:with-param name="months" select="r:sets/r:month"/>
            </xsl:call-template>
        </payload>
    </xsl:template>

</xsl:stylesheet>


回答2:

That's because the rule match="month" is a different to match="{http://www.castiron.com/response}month". They have the same node name but since they're in different namespaces they're considered different nodes.