如何用XPath从<ul><li>中选取名称并获取对应值(XSL 1.0)
在XSLT 1.0中简便提取HTML字符串中
- 的对应值
因为XSLT 1.0无法直接解析字符串形式的HTML结构,我们可以通过两种方案实现类似属性访问的简便提取方式:
方案一:利用扩展函数将字符串转为节点集(推荐,处理器支持时使用)
借助扩展函数把HTML字符串转换成可导航的节点集,之后就能用XPath直接查询目标内容。
步骤1:定义扩展命名空间
根据你使用的XSLT处理器选择对应命名空间:
- 微软MSXML处理器:用
urn:schemas-microsoft-com:xslt - 支持EXSLT的处理器(如Saxon):用
http://exslt.org/common
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxml="urn:schemas-microsoft-com:xslt" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="msxml exsl">
步骤2:转换HTML字符串为节点集
<!-- 获取原始HTML字符串 --> <xsl:variable name="raw-html" select="custom_options/custom_option/value" /> <!-- 将字符串转为临时节点(关闭转义以保留HTML标签) --> <xsl:variable name="temp-nodes"> <xsl:value-of select="$raw-html" disable-output-escaping="yes" /> </xsl:variable> <!-- 转为可查询的节点集(根据处理器选msxml或exsl) --> <xsl:variable name="html-node-set" select="msxml:node-set($temp-nodes)" />
步骤3:用XPath提取目标值
现在可以像操作普通XML节点一样,通过<strong>标签的文本定位对应的值:
<!-- 获取"Breedte (mm):"对应的值 --> <xsl:value-of select="$html-node-set//li[normalize-space(strong)='Breedte (mm):']/text()[normalize-space()]" /> <!-- 获取"Type kast:"对应的值 --> <xsl:value-of select="$html-node-set//li[normalize-space(strong)='Type kast:']/text()[normalize-space()]" />
方案二:递归模板拆分字符串(无扩展依赖时使用)
如果处理器不支持扩展函数,可以通过递归模板拆分HTML字符串,将每个<li>的键值对提取为节点,再通过名称查询。
步骤1:编写递归解析模板
<!-- 存储解析后的键值节点集 --> <xsl:variable name="parsed-options"> <xsl:call-template name="parse-li-items"> <xsl:with-param name="text" select="custom_options/custom_option/value" /> </xsl:call-template> </xsl:variable> <xsl:template name="parse-li-items"> <xsl:param name="text" /> <!-- 定位第一个<li>的内容 --> <xsl:variable name="li-content" select="substring-after($text, '<li>')" /> <xsl:if test="$li-content != $text"> <xsl:variable name="li-end" select="substring-before($li-content, '</li>')" /> <!-- 提取名称(<strong>内的文本) --> <xsl:variable name="option-name" select="normalize-space(substring-before(substring-after($li-end, '<strong>'), '</strong>'))" /> <!-- 提取对应的值 --> <xsl:variable name="option-value" select="normalize-space(substring-after($li-end, '</strong>'))" /> <!-- 生成键值节点 --> <option name="{$option-name}"><xsl:value-of select="$option-value" /></option> <!-- 递归处理剩余的<li> --> <xsl:call-template name="parse-li-items"> <xsl:with-param name="text" select="substring-after($text, '</li>')" /> </xsl:call-template> </xsl:if> </xsl:template>
步骤2:查询目标值
将存储的节点集转换为可查询的集合后,通过名称访问:
<xsl:variable name="options-node-set" select="msxml:node-set($parsed-options)" /> <!-- 获取"Breedte (mm):"对应的值 --> <xsl:value-of select="$options-node-set/option[@name='Breedte (mm):']" /> <!-- 获取"Type kast:"对应的值 --> <xsl:value-of select="$options-node-set/option[@name='Type kast:']" />
优势对比
相比你之前嵌套substring-before/substring-after的写法,上述方案:
- 可读性更强,无需拼接复杂的字符串匹配规则
- 可维护性更高,新增或修改字段只需调整查询的名称即可
- 逻辑更清晰,将HTML结构解析为可导航的节点后,符合XPath的使用习惯
内容的提问来源于stack exchange,提问作者Wouter van Domselaar
相关产品推荐
相关产品推荐

