繁体   English   中英

如何在xsl if中使用xsl变量

[英]How to use xsl variable in xsl if

我试图将xsl变量中的值分配给我的xml文件中的新节点。 此代码有效,但当“lbi:GetCoordinates(PVAL)”的值为空时添加一个空的PROP / PVAL节点:

<xsl:template match="PROP" mode="Geocode">
<PROP NAME="Geocode">
    <PVAL>
      <xsl:value-of select="lbi:GetCoordinates(PVAL)"/>
    </PVAL>
 </PROP>
 </xsl:template>

由于我不想要任何空节点,我只想在“lbi:GetCoordinates(PVAL)”的值不为空时才添加新节点。 我正在尝试的方法是将值赋给变量并测试该变量,如下所示。 不幸的是,当我这样做时,我没有得到新的PROP节点,即使lbi:GetCoordinates(PVAL)返回非空值。

<xsl:template match="PROP" mode="Geocode">
<xsl:variable name="coords" select="'lbi:GetCoordinates(PVAL)'"/>
<xsl:if test="not(string-length(coords) = 0)">
  <PROP NAME="Geocode">
    <PVAL>
      <xsl:value-of select="coords"/>
    </PVAL>
  </PROP>
</xsl:if>
</xsl:template>

任何人都可以指出我正确的方向,或建议一个更好的方法来实现这一目标吗?

源xml是这样的:

<RECORD>
<PROP name="PostCode">
<PVAL>N11 1NN</PVAL>
</PROP>
</RECORD>

并且模板被引用:

<xsl:template match="RECORD">
<xsl:copy>
  <xsl:apply-templates select="PROP[@NAME='PostCode']" mode="Geocode"/>
</xsl:copy>

lbi:GetCoordinates()方法在作为xml命名空间添加的外部.Net程序集中。


使用这种方法有效:

<xsl:template match="PROP[string-length(lbi:GetCoordinates(PVAL))>0]" mode="Geocode">
  <PROP NAME="Geocode">
    <PVAL>
      <xsl:value-of select="lbi:GetCoordinates(PVAL)"/>
    </PVAL>
  </PROP>

现在的问题是lbi:GetCoordinates方法只需要调用一次就被调用两次,源xml可以有100,000多个需要地理编码的元素,所以这是非常重要的。 这告诉我,我之前使用的xsl:variable表达式是不正确的,变量总是最终为空。

<xsl:variable name="coords" select="'lbi:GetCoordinates(PVAL)'"/> 
<xsl:if test="not(string-length(coords) = 0)"> 

这几乎是“正确的”。 唯一的问题是lbi:GetCoordinates(PVAL)周围的报价lbi:GetCoordinates(PVAL) 这些将返回值从扩展函数转换为调用此函数的表达式的字符串。 由于此字符串的长度明显大于0 ,因此第二行的测试将始终为真。

从这里开始,我认为lbi:GetCoordinates()函数返回一个字符串或一个原子值(不是一个节点或一个节点集) ,因为你还没有说过函数的返回类型,但这是非常的重要!

你想要的 (请注意,现在缺少引号!):

<xsl:variable name="coords" select="lbi:GetCoordinates(PVAL)"/> 
<xsl:if test="not(string-length(coords) = 0)"> 

**但即使这有点笨拙。

解决方案 :使用XSLT模板匹配模式的强大功能,并完全避免模板中的条件逻辑:

<xsl:template match="PROP[string-length(lbi:GetCoordinates(PVAL))]"
     mode="Geocode">
  <PROP NAME="Geocode">                     
    <PVAL>                     
      <xsl:value-of select="lbi:GetCoordinates(PVAL)"/>                     
    </PVAL>                     
   </PROP>
 </xsl:template> 

不要担心lbi:GetCoordinates(PVAL)函数被调用两次,因为一个好的优化XSLT处理器只会调用一次 您可以随时进行一些测试,看看是否是这种情况。

在最坏的情况下,如果XSLT处理器是哑的并且调用该函数两次,那么使用上面的clumsier代码。

尝试使用string-length(coords) > 0而不是您的条件。

如果你的source-xml看起来像这样:

<PROP>
  <lbi:GetCoordinates(PVAL)>sometext</lbi:Getcoordinates(PVAL>
</PROP>

这应该做的伎俩:

<xsl:template match="PROP[string-length(lbi:GetCoordinates(PVAL))>0]" mode="Geocode">
    <PROP NAME="Geocode">
        <PVAL>
          <xsl:value-of select="lbi:GetCoordinates(PVAL)"/>
        </PVAL>
     </PROP>
</xsl:template>

我将match-clause更改为提前过滤,您也可以尝试将if语句从not(string-length()=0)更改为string-length>0

我目前没有环境来测试它,考虑包括你的source-xml,因为它对xslt的构造方式至关重要

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM