XSLT-regex仅从text()节点选择一位数字
我有这样的xmlXSLT-regex仅从text()节点选择一位数字,regex,xml,xslt,xslt-2.0,Regex,Xml,Xslt,Xslt 2.0,我有这样的xml <section> <para>height 4cm, width 5cm, weight 343</para> <para>height 2cm, width 6cm, weight 410</para> <para>height 3cm, width 1cm, weight 590</para> </section> <xsl:template m
<section>
<para>height 4cm, width 5cm, weight 343</para>
<para>height 2cm, width 6cm, weight 410</para>
<para>height 3cm, width 1cm, weight 590</para>
</section>
<xsl:template match="para/text()">
<xsl:analyze-string select="." regex="\d">
<xsl:matching-substring>
<xsl:value-of select="2 * number(.)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
要做到这一点,我有一个这样的模板
<section>
<para>height 4cm, width 5cm, weight 343</para>
<para>height 2cm, width 6cm, weight 410</para>
<para>height 3cm, width 1cm, weight 590</para>
</section>
<xsl:template match="para/text()">
<xsl:analyze-string select="." regex="\d">
<xsl:matching-substring>
<xsl:value-of select="2 * number(.)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
这里的问题是,这把没有一个数字的数字作为一个数字乘以一,然后把它们加倍
电流输出
<section>
<para>height 8cm, width 10cm, weight 686</para>
<para>height 4cm, width 12cm, weight 820</para>
<para>height 6cm, width 2cm, weight 10180</para>
</section>
高8厘米,宽10厘米,重686
高4厘米,宽12厘米,重820磅
身高6厘米,宽2厘米,体重10180
有什么建议可以解决这个问题吗?有几种方法可以解决这个问题。一种方法是要求单个数字后面跟“cm”(如果在输入XML中总是这样,我们还不知道) XSLT样式表
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="para/text()">
<xsl:analyze-string select="." regex="\dcm">
<xsl:matching-substring>
<xsl:value-of select="2 * number(substring-before(.,'cm'))"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:transform>
<section>
<para>height 8, width 10, weight 343</para>
<para>height 4, width 12, weight 410</para>
<para>height 6, width 2, weight 590</para>
</section>
XML输出
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="para/text()">
<xsl:analyze-string select="." regex="\dcm">
<xsl:matching-substring>
<xsl:value-of select="2 * number(substring-before(.,'cm'))"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:transform>
<section>
<para>height 8, width 10, weight 343</para>
<para>height 4, width 12, weight 410</para>
<para>height 6, width 2, weight 590</para>
</section>
高8,宽10,重343
高4,宽12,重410
高6,宽2,重590
或者,您可以例如要求单个数字后面跟一些非数字:
<xsl:template match="para/text()">
<xsl:analyze-string select="." regex="\d[^\d]">
<xsl:matching-substring>
<xsl:value-of select="2 * number(substring(.,1,1))"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
如果这总是适用于您的数据,因为它不包括字符串末尾有一个数字的情况
要考虑所有可能的情况,请使用
<xsl:template match="para/text()">
<xsl:analyze-string select="." regex="(^|[^\d])(\d)([^\d]|$)">
<xsl:matching-substring>
<xsl:value-of select="regex-group(1)"/>
<xsl:value-of select="2 * number(regex-group(2))"/>
<xsl:value-of select="regex-group(3)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
这与michael.hor257k(在我之前!)的建议基本相同。如果将“单位数”定义为由非数字字符包围的单位数,则可以使用:
<xsl:template match="para/text()">
<xsl:analyze-string select="." regex="(\D)(\d)(\D)">
<xsl:matching-substring>
<xsl:value-of select="regex-group(1)"/>
<xsl:value-of select="2 * number(regex-group(2))"/>
<xsl:value-of select="regex-group(3)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
请注意,这不会捕获字符串开头或结尾的单个数字。要包含这些,您必须使用:
<xsl:analyze-string select="." regex="(^|\D)(\d)(\D|$)">
您可以使用“\b\d\b”
仅匹配一位整数。但是,这不会考虑上下文(您可能有兴趣更改所有cm
单位值-然后将下面的答案与\d+cm
表达式一起使用)。@Stribizev我不确定XSLT中是否允许\b
,我得到:正则表达式中的错误:net.sf.saxon.trans.XPathException:正则表达式中字符2处的语法错误:不允许转义字符“b”
@MathiasMüller:你说得对。我在官方文件中查找,但在SO上找到:)。不过,如果您计划在cm
之前匹配数字,则不需要仅限制为1位数。@Stribizev,好主意。您有两个问题:(1)您正在丢弃以下非数字字符,将1cm
转换为2m
;(2) 您正在处理一个多位数的最后一个数字-将111kg
转换为112g
@michael.hor257k谢谢您的评论,我现在修复了第一个问题-查看第二个问题。您已经修复了(1),但没有修复(2)。@michael.hor257k那么它应该是(^.[^\d])(\d)([^\d].$)
,这就是你已经提出的建议。