如何在XSL中筛选开头含特殊字符后接W的问题节点?
问题解决:筛选Question内容中前置特殊字符/空格后以W开头的条目
问题描述
现有如下XML文档:
<paper> <Question_01> <QNo>1a</QNo> <Question>What is Semantic Web? </Question> </Question_01> <Question_01> <QNo>1b</QNo> <Question>“Web 2.0 applications can be used to increase the profit of a business“ Discuss.</Question> </Question_01> <Question_01> <QNo>1c</QNo> <Question>Discuss the advantage of the Extensible Markup Language.</Question> </Question_01> </paper>
需求是筛选出Question内容中实际有效内容以W开头的条目(包括1a和1b),但原XSL代码仅能选中1a:
<xsl:for-each select = "paper/Question_01"> <xsl:if test = "starts-with(Question, 'W')"> <li> <xsl:value-of select = "Question"/> </li> </xsl:if> </xsl:for-each>
问题在于原代码仅检查Question文本的第一个字符是否为W,而1b的文本开头是全角引号“,无法匹配;同时也不兼容开头有空格、其他特殊符号的情况。
解决方案
方案1:兼容XSLT 1.0版本
通过嵌套translate函数先过滤掉所有非字母字符,再检查是否以W开头,同时用normalize-space处理首尾空格:
<xsl:for-each select = "paper/Question_01"> <xsl:if test = "starts-with( translate( normalize-space(Question), translate(normalize-space(Question), 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', ''), '' ), 'W' )"> <li> <xsl:value-of select = "Question"/> </li> </xsl:if> </xsl:for-each>
逻辑说明:
normalize-space(Question):去除文本首尾空格,合并中间连续空格- 内层
translate(..., 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', ''):提取文本中所有非字母的字符 - 外层
translate(..., [非字母字符], ''):从原归一化文本中移除所有非字母字符,得到纯字母开头的文本 starts-with(..., 'W'):检查处理后的文本是否以W开头
方案2:XSLT 2.0及以上版本(更简洁)
利用正则表达式matches函数,直接匹配开头的任意空格、非字母字符后接W的情况:
<xsl:for-each select = "paper/Question_01"> <xsl:if test = "matches(Question, '^\s*[^a-zA-Z]*W')"> <li> <xsl:value-of select = "Question"/> </li> </xsl:if> </xsl:for-each>
正则说明:
^:匹配文本开头\s*:匹配0个或多个空格[^a-zA-Z]*:匹配0个或多个非字母字符W:匹配大写W(如需兼容小写w,可添加i标志:matches(Question, '^\s*[^a-zA-Z]*w', 'i'))
内容的提问来源于stack exchange,提问作者RUNR
相关产品推荐
相关产品推荐

