Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XSLT-regex仅从text()节点选择一位数字_Regex_Xml_Xslt_Xslt 2.0 - Fatal编程技术网

XSLT-regex仅从text()节点选择一位数字

XSLT-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

我有这样的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 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].$)
,这就是你已经提出的建议。