我正在尝试将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()方法在一个外部.Net程序集中添加为xml名称空间。
使用这种方法有效:
<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表达式不正确,变量总是以空为止。
答案 0 :(得分:4)
<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代码。
答案 1 :(得分:0)
尝试使用string-length(coords) > 0
代替您的条件。
答案 2 :(得分: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的构造方式至关重要