XSLT - 通过使用正则表达式识别模式来替换文本节点
XSLT - replace text node by identifying patterns using regex
我有 x xml 这样的,
<doc>
<p>ABC Number 132, Decimal 321, AAB Double 983 DEF GHI 432 JKL</p>
</doc>
我的 objective 是什么,如果 'Number'、'Decimal'、'Double' 后跟 space (' ') 后跟数字,那么中间 space 值应替换为 * 字符。
所以输出应该是,
<doc>
<p>ABC Number*132, Decimal*321, AAB Double*983 DEF GHI 432 JKL</p>
</doc>
为此我有以下 xsl,
<xsl:template match="p">
<xsl:analyze-string select="text()" regex="(Number/s/d)|(Decimal/s/d)|(Double/s/d)">
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="regex-group(1)">
<xsl:value-of select="'Number*'"/>
</xsl:when>
<xsl:when test="regex-group(2)">
<xsl:value-of select="'Decimal*'"/>
</xsl:when>
<xsl:when test="regex-group(3)">
<xsl:value-of select="'Double*'"/>
</xsl:when>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
但是 return 不是正确的结果..
有什么建议可以修改我的代码以获得正确的输出吗?
正则表达式中的主要问题是您试图将 space 和数字与 /s
和 /d
匹配。
应该是\s
和\d
。
但是,即使您修复了这个问题,您仍然会丢失数字,因为您没有捕获它。
您还失去了 p
元素。
我建议使用更简单的正则表达式并添加 xsl:copy
以保持 p
...
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<xsl:copy>
<xsl:analyze-string select="." regex="(Number|Decimal|Double)\s(\d)">
<xsl:matching-substring>
<xsl:value-of select="concat(regex-group(1),'*',regex-group(2))"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出
<doc>
<p>ABC Number*132, Decimal*321, AAB Double*983 DEF GHI 432 JKL</p>
</doc>
更简单更短:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()">
<xsl:value-of select="replace(., '(Number|Decimal|Double) (\d+)', '*')"/>
</xsl:template>
</xsl:stylesheet>
我有 x xml 这样的,
<doc>
<p>ABC Number 132, Decimal 321, AAB Double 983 DEF GHI 432 JKL</p>
</doc>
我的 objective 是什么,如果 'Number'、'Decimal'、'Double' 后跟 space (' ') 后跟数字,那么中间 space 值应替换为 * 字符。
所以输出应该是,
<doc>
<p>ABC Number*132, Decimal*321, AAB Double*983 DEF GHI 432 JKL</p>
</doc>
为此我有以下 xsl,
<xsl:template match="p">
<xsl:analyze-string select="text()" regex="(Number/s/d)|(Decimal/s/d)|(Double/s/d)">
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="regex-group(1)">
<xsl:value-of select="'Number*'"/>
</xsl:when>
<xsl:when test="regex-group(2)">
<xsl:value-of select="'Decimal*'"/>
</xsl:when>
<xsl:when test="regex-group(3)">
<xsl:value-of select="'Double*'"/>
</xsl:when>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
但是 return 不是正确的结果..
有什么建议可以修改我的代码以获得正确的输出吗?
正则表达式中的主要问题是您试图将 space 和数字与 /s
和 /d
匹配。
应该是\s
和\d
。
但是,即使您修复了这个问题,您仍然会丢失数字,因为您没有捕获它。
您还失去了 p
元素。
我建议使用更简单的正则表达式并添加 xsl:copy
以保持 p
...
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<xsl:copy>
<xsl:analyze-string select="." regex="(Number|Decimal|Double)\s(\d)">
<xsl:matching-substring>
<xsl:value-of select="concat(regex-group(1),'*',regex-group(2))"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出
<doc>
<p>ABC Number*132, Decimal*321, AAB Double*983 DEF GHI 432 JKL</p>
</doc>
更简单更短:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()">
<xsl:value-of select="replace(., '(Number|Decimal|Double) (\d+)', '*')"/>
</xsl:template>
</xsl:stylesheet>