XSLT 1.0实施递归模板时遇到问题

时间:2018-06-26 07:29:03

标签: xml xslt xslt-1.0

我对XSLT还是很陌生,一直在努力实现递归模板,该模板遍历多个文本节点并搜索匹配项。创建递归模板时,出现一条错误消息,提示“'/'的第一个操作数的必需项类型为node();提供的值具有项类型xs:string”。我不知道如何选择多个节点而不是字符串。

目标:我有多个测试节点,例如

<Chain>1 3 4 7 20 50 72 ...</Chain>

我想遍历这些节点以寻找匹配的数字。找到此数字后,我需要选择父母的element属性的子字符串。

这是带有递归模板的样式表的一部分:

<xsl:template match="/l:LandXML/h:HexagonLandXML/h:Point/h:PointCode">
<xsl:variable name="id2" select="../@uniqueID"/>
  <xsl:call-template name="tests">
  <xsl:with-param name="input" select="/l:LandXML/h:HexagonLandXML/h:PlanFeature/h:CoordGeom/h:Spline/h:Chain"/>
  <xsl:with-param name="id" select="$id2"/>
  </xsl:call-template>
</xsl:template>

<xsl:template name="tests">
<xsl:param name="id"/>
<xsl:param name="input"/>
<xsl:choose>
    <xsl:when test="substring-before($input, ' ') = $id">
        <xsl:value-of select="format-number(substring-before(substring-after($input/../@oID, '_'), '_'), '#')"/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:call-template name="tests">
            <xsl:with-param name="input" select="substring-after($input, ' ')"/>
            <xsl:with-param name="id" select="$id"/>
        </xsl:call-template>
    </xsl:otherwise>
</xsl:choose>
</xsl:template>

为了更好地理解,完整的XML和XSLT在这里:https://xsltfiddle.liberty-development.net/94hvTzd/17

在此先感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

所以你想知道是否

<Chain>1 3 4 7 20 50 72 ...</Chain>

包含50吗?

这里不需要递归模板。 XPath字符串函数可以做到这一点。对于XPath 1.0,使用

//Chain[contains(concat(' ', ., ' '), concat(' ', $val, ' '))]

其中$val'50'concat()确保没有部分匹配,并且找到开头和结尾的匹配。

对于XPath 2.0及更高版本,您可以使用tokenize()

//Chain[tokenize(., ' ') = $val]

答案 1 :(得分:1)

您在<xsl:with-param name="input" select="substring-after($input, ' ')"/>中的模板传递一个字符串值,该字符串值没有父节点,因此您必须将原始元素作为单独的参数存储/传递。请注意,您在xsltfiddle可以访问(并且正在使用它)XSLT 3处理器Saxon 9.8 HE,在这里您可以通过使用例如避免使用递归模板的麻烦。 tokenize(Chain, ' ')[. = $id]或类似的内容。

相关问题