XSLT +正则表达式替换

时间:2016-03-07 09:21:57

标签: regex xml xslt

我有这样的XML代码段:

...
<housenumber>23</housenumber>
...
<housenumber>453a</housenumber>
...
<housenumber>76-79</housenumber>
...
<housenumber>12 foo bar something 43</housenumber>
...

如何使用XSLT将这些住宅数量分成两部分,以便我得到两个变量 - 第一个包含&#34;从第1位到第一次出现非数字字符的所有内容&#34;第二个包含&#34;其他一切&#34;?

这样的事情:

...
<housenumber>23</housenumber>
<!-- v1 = 23, v2 = null -->
...
<housenumber>453a</housenumber>
<!-- v1 = 453, v2 = a -->
...
<housenumber>76-79</housenumber>
<!-- v1 = 76, v2 = -79 -->
...
<housenumber>12 foo bar something 43</housenumber>
<!-- v1 = 12, v2 = foo bar something 43 -->
...

任何提示/想法?

感谢。

1 个答案:

答案 0 :(得分:2)

正如评论中已经指出的,analyze-string可以提供帮助,这是一个使用XSLT 3.0(由Saxon 9.7或Exselt支持)的示例,它使用了XPath 3.0函数analyze-string({ {3}})

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math fn"
    version="3.0">

    <xsl:template match="root">
        <xsl:variable name="matches" select="housenumber/analyze-string(., '(^[0-9]+)([^0-9]?.*)')//fn:match"/>
        <xsl:variable name="v1" select="$matches//fn:group[@nr = 1]/xs:integer(.)"/>
        <xsl:variable name="v2" select="$matches//fn:group[@nr = 2]/string()"/>
        <integers>
            <xsl:value-of select="$v1" separator=","/>
        </integers>
        <strings>
            <xsl:value-of select="$v2" separator=","/>
        </strings>
    </xsl:template>
</xsl:stylesheet>

使用样本

<root>
    <housenumber>23</housenumber>
    ...
    <housenumber>453a</housenumber>
    ...
    <housenumber>76-79</housenumber>
    ...
    <housenumber>12 foo bar something 43</housenumber>
</root>

我得到了输出

<integers>23,453,76,12</integers><strings>,a,-79, foo bar something 43</strings>

使用XSLT 2.0,您可以使用xsl:analyze-string指令:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:template match="root">
        <xsl:variable name="matches" as="element(match)*">
            <xsl:apply-templates select="housenumber"/>
        </xsl:variable>
        <xsl:variable name="v1" select="$matches//group[@nr = 1]/xs:integer(.)"/>
        <xsl:variable name="v2" select="$matches//group[@nr = 2]/string()"/>
        <integers>
            <xsl:value-of select="$v1" separator=","/>
        </integers>
        <strings>
            <xsl:value-of select="$v2" separator=","/>
        </strings>
    </xsl:template>

    <xsl:template match="housenumber">
        <xsl:analyze-string select="." regex="(^[0-9]+)([^0-9]?.*)">
            <xsl:matching-substring>
                <match>
                    <group nr="1">
                        <xsl:value-of select="regex-group(1)"/>
                    </group>
                    <group nr="2">
                        <xsl:value-of select="regex-group(2)"/>
                    </group>
                </match>
            </xsl:matching-substring>
        </xsl:analyze-string>
    </xsl:template>

</xsl:stylesheet>