我试图将xsl变量中的值分配给我的xml文件中的新节点.此代码有效,但当“lbi:GetCoordinates(PVAL)”的值为空时添加一个空的PROP / PVAL节点: xsl:template match="PROP" mode="Geocode"PROP NAME="Geocode" PV
<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).这些将返回值从扩展函数转换为调用此函数的表达式的字符串.由于此字符串的长度明显大于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代码.