使 XSLT 方法在不同时间表现不同(可能使用参数?)

Making an XSLT method behave differently at different times (maybe with a parameter?)

所以我有一行代码:

<xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber" />

从 XML 中获取 phone 数值,无论是在我表单的 Phone 数值字段中输入的 phone 数值。我们称它为 555-867-5309。

当上面的行是运行时,调用模板的代码如下:

<xsl:template match="PhoneNumber">
    <xsl:if test="(. != '')">
        <xsl:call-template name="StringBreakUp"> <!-- Area Code -->
            <xsl:with-param name="text" select="." />
            <xsl:with-param name="current-position" select="2" />
            <xsl:with-param name="remaining-length" select="4" />
            <xsl:with-param name="max-size" select="5" />
        </xsl:call-template>
        <xsl:call-template name="fieldSeparator" />
    </xsl:if>
</xsl:template>

它获取了 phone 号码的区号,所以它以 555 结束,就像我想要的那样。

但是我需要一种方法来获得正确的 phone 号码,也就是说,867-5309。可以这样抢:

<xsl:template match="PhoneNumber2">
    <xsl:if test="(. != '')">
        <xsl:call-template name="StringBreakUp"> <!-- Phone Number -->
            <xsl:with-param name="text" select="." />
            <xsl:with-param name="current-position" select="6" />
            <xsl:with-param name="remaining-length" select="4" />
            <xsl:with-param name="max-size" select="14" />
        </xsl:call-template>
        <xsl:call-template name="fieldSeparator" />
    </xsl:if>
</xsl:template>

不幸的是,我无法像第一个那样调用该模板:

<xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber2" />

因为 XML 中没有任何东西叫做 PhoneNumber2.

我能想到的最好办法就是打电话

<xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber" />

两次。但是,这就是问题所在,我无法想出一种方法来区分它需要获取区号的时间(第一次调用模板)和它需要的时间获取 phone 正确的数字(第二次调用该方法)。

所以我正在寻找的是:

<xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber" />
<xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber" />

<xsl:template match="NewPhoneNumber">
    <xsl:if test="(. != '')"> **AND FIRST TIME CALLING THIS METHOD**
        <xsl:call-template name="StringBreakUp"> <!-- Area Code -->
            <xsl:with-param name="text" select="." />
            <xsl:with-param name="current-position" select="2" />
            <xsl:with-param name="remaining-length" select="4" />
            <xsl:with-param name="max-size" select="5" />
        </xsl:call-template>
        <xsl:call-template name="fieldSeparator" />
    </xsl:if>
    <xsl:if test="(. != '')"> **AND NOT FIRST TIME REACHING THIS METHOD**
        <xsl:call-template name="StringBreakUp"> <!-- Phone Number -->
            <xsl:with-param name="text" select="." />
            <xsl:with-param name="current-position" select="6" />
            <xsl:with-param name="remaining-length" select="4" />
            <xsl:with-param name="max-size" select="14" />
        </xsl:call-template>
        <xsl:call-template name="fieldSeparator" />
    </xsl:if>
</xsl:template>

但我不知道如何使用:

<xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber" />

带有一个参数,这样我就可以区分我们正在遍历整个 phone 号码的时间。

XSLT

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

<xsl:template name="Arguments">
    <xsl:call-template name="fieldSeparator" />
    <xsl:apply-templates select="/MyQuery/Arguments/Name" />
    <xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber" />
    <xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber" />
</xsl:template>

<xsl:template match="Name"> 
    <xsl:if test="(. != '')">
        <xsl:copy-of select="." />
        <xsl:call-template name="fieldSeparator" />
    </xsl:if>
</xsl:template>

<xsl:template match="PhoneNumber">
    <xsl:if test="(. != '')">
        <xsl:call-template name="StringBreakUp"> <!-- Area Code -->
            <xsl:with-param name="text" select="." />
            <xsl:with-param name="current-position" select="2" />
            <xsl:with-param name="remaining-length" select="4" />
            <xsl:with-param name="max-size" select="5" />
        </xsl:call-template>
        <xsl:call-template name="fieldSeparator" />
    </xsl:if>
</xsl:template>


<xsl:template match="PhoneNumber2">
    <xsl:if test="(. != '')">
        <xsl:call-template name="StringBreakUp"> <!-- Phone Number -->
            <xsl:with-param name="text" select="." />
            <xsl:with-param name="current-position" select="6" />
            <xsl:with-param name="remaining-length" select="4" />
            <xsl:with-param name="max-size" select="14" />
        </xsl:call-template>
        <xsl:call-template name="fieldSeparator" />
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

XML

< MyQuery >

< Arguments >

    < Name >NNN</ Name >

    < PhoneNumber >(555)867-5309</ PhoneNumber >

</ Arguments >

</ MyQuery >

当前输出 NNN 555 555

期望的输出 NNN 555 867-5309

到现在为止,老实说,我不明白为什么你的代码应该那么复杂。对于简单的字符串操作(比如只获取字符串的一部分),不需要命名模板。

此外,在我看来,拆分一个字符串并以复杂的方式检索两个部分是没有意义的 - 只能将它们一个接一个地输出。

XML 输入

<MyQuery>
    <Arguments>
        <Name>NNN</Name>
        <PhoneNumber>(555)867-5309</PhoneNumber>
    </Arguments>
</MyQuery>

XSLT 样式表

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="text"/>

    <xsl:strip-space elements="*"/>

    <xsl:template match="Arguments">
      <xsl:value-of select="concat(Name,translate(PhoneNumber,'()','  '))"/>
    </xsl:template>

</xsl:transform>

文本输出

NNN 555 867-5309

就像 Matthias 在他的回答中所说的那样,您使用单独的模板甚至参数使事情过于复杂。话虽如此,下面应该按照您最初的要求进行操作,即基于参数值的不同行为。除非您有可以简化 XSL 的理由,否则它可能对您有用。

我从 XSL 下面省略了不相关的部分。

<xsl:template name="Arguments">
    <xsl:call-template name="fieldSeparator" />
    <xsl:apply-templates select="/MyQuery/Arguments/Name" />
    <xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber" >
        <xsl:with-param name="areaCode">true</xsl:with-param>
    </xsl:apply-templates>
    <xsl:apply-templates select="/MyQuery/Arguments/PhoneNumber">
        <xsl:with-param name="areaCode">false</xsl:with-param>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="PhoneNumber">
    <xsl:param name="areaCode" />
    <xsl:if test="(. != '')">
        <xsl:choose>
            <xsl:when test="$areaCode='true'">
                <xsl:call-template name="StringBreakUp"> <!-- Area Code -->
                    <xsl:with-param name="text" select="." />
                    <xsl:with-param name="current-position" select="2" />
                    <xsl:with-param name="remaining-length" select="4" />
                    <xsl:with-param name="max-size" select="5" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:call-template name="StringBreakUp"> <!-- Phone Number -->
                    <xsl:with-param name="text" select="." />
                    <xsl:with-param name="current-position" select="6" />
                    <xsl:with-param name="remaining-length" select="4" />
                    <xsl:with-param name="max-size" select="14" />
                </xsl:call-template>
                <xsl:call-template name="fieldSeparator" />
            </xsl:otherwise>
            <xsl:call-template name="fieldSeparator" />
        </xsl:choose>
    </xsl:if>
</xsl:template>

您的问题所问的答案——即如何将两个不同的模板应用于同一节点——是使用模式

例如:

<xsl:template match="/">
    <xsl:apply-templates select="MyQuery/Arguments/PhoneNumber" mode="area"/>
    <xsl:apply-templates select="MyQuery/Arguments/PhoneNumber" />
</xsl:template>

<xsl:template match="PhoneNumber" mode="area">
    <!-- code to extract the area -->
</xsl:template>

<xsl:template match="PhoneNumber">
    <!-- code to extract the number -->
</xsl:template>

另一种选择是(直接)使用命名模板,例如

<xsl:template match="/">
    <xsl:variable name="pNum" select="MyQuery/Arguments/PhoneNumber"/>
    <xsl:call-template name="get-area">
        <xsl:with-param name="text" select="$pnum"/>
    </xsl:call-template>
    <xsl:call-template name="get-number">
        <xsl:with-param name="text" select="$pnum"/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="get-area">
    <!-- code to extract the area -->
</xsl:template>

<xsl:template match="get-number">
    <!-- code to extract the number -->
</xsl:template>