在XSLT中转义输入

时间:2016-09-29 18:53:41

标签: xml xslt

我有以下XSLT,它通过对给定数组上的键进行分组来格式化输出:

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


    <xsl:param name="values" select="'Sniper 50 Red', 'Xiper 10 Red'"/>

    <xsl:output indent="yes"/>

    <xsl:function name="mf:match" as="xs:string">
        <xsl:param name="input" as="xs:string"/>
        <xsl:param name="values" as="xs:string*"/>
        <xsl:sequence
            select="if ($values[matches($input, concat('^', .))])
                    then $values[matches($input, concat('^', .))]
                    else $input"/>
    </xsl:function>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="results">
        <xsl:copy>
            <xsl:for-each-group select="pageFunctionResult" group-by="mf:match(product_name, $values)">
                <xsl:choose>
                    <xsl:when test="product_name ne current-grouping-key()">
                            <xsl:copy>
                                <position>MAINPRODUCT</position>
                                <variantname>
                                    <xsl:value-of select="product_name"/>
                                </variantname>
                                <product_namea>
                                    <xsl:value-of select="current-grouping-key()"/>
                                </product_namea>
                                <xsl:copy-of select="category, product_id, quantity, manufacturer,image"/>
                                <xsl:apply-templates select="current-group() except ."/>
                            </xsl:copy>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:for-each select="current-group()">
                        <xsl:copy>
                            <position>MAINPRODUCT</position>
                            <variantname>
                                <xsl:value-of select="current-grouping-key()"/>
                            </variantname>
                            <xsl:apply-templates select="*"/>
                        </xsl:copy>
                        </xsl:for-each>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="pageFunctionResult">
        <variant id="{position()}">
            <xsl:apply-templates/>
        </variant>
    </xsl:template>

</xsl:transform>

在这里,您可以看到it in action。它工作得很好,但我现在的名字中带有括号的键:

<xsl:param name="values" select="'Sniper 50 Red (26)', 'Xiper 10 Red (27)'"/>

...这显然会使代码失效,因为括号在正则表达式中保留。所以括号应该被转义。我得到了使用functx:escape-for-regex的提示,但我无法将其实现到代码中。

1 个答案:

答案 0 :(得分:1)

此示例显示如何使用functx函数:

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

    <xsl:param name="values" select="'Sniper 50 Red (26)', 'Xiper 10 Red (27)'"/>

    <xsl:output indent="yes"/>

    <xsl:function name="functx:escape-for-regex" as="xs:string"
        >
        <xsl:param name="arg" as="xs:string?"/>

        <xsl:sequence select="
            replace($arg,
            '(\.|\[|\]|\\|\||\-|\^|\$|\?|\*|\+|\{|\}|\(|\))','\\$1')
            "/>

    </xsl:function>

    <xsl:function name="mf:match" as="xs:string">
        <xsl:param name="input" as="xs:string"/>
        <xsl:param name="values" as="xs:string*"/>
        <xsl:sequence
            select="if ($values[matches($input, concat('^', functx:escape-for-regex(.)))])
            then $values[matches($input, concat('^', functx:escape-for-regex(.)))]
            else $input"/>
    </xsl:function>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="results">
        <xsl:copy>
            <xsl:for-each-group select="pageFunctionResult" group-by="mf:match(product_name, $values)">
                <xsl:choose>
                    <xsl:when test="product_name ne current-grouping-key()">
                        <xsl:copy>
                            <position>MAINPRODUCT</position>
                            <variantname>
                                <xsl:value-of select="product_name"/>
                            </variantname>
                            <product_namea>
                                <xsl:value-of select="current-grouping-key()"/>
                            </product_namea>
                            <xsl:copy-of select="category, product_id, quantity, manufacturer,image"/>
                            <xsl:apply-templates select="current-group() except ."/>
                        </xsl:copy>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:for-each select="current-group()">
                            <xsl:copy>
                                <position>MAINPRODUCT</position>
                                <variantname>
                                    <xsl:value-of select="current-grouping-key()"/>
                                </variantname>
                                <xsl:apply-templates select="*"/>
                            </xsl:copy>
                        </xsl:for-each>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="pageFunctionResult">
        <variant id="{position()}">
            <xsl:apply-templates/>
        </variant>
    </xsl:template>

</xsl:transform>