使 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>
所以我有一行代码:
<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>