XSLT 2.0匹配元素的内容与关键字列表

时间:2014-03-31 15:22:22

标签: xml xslt

我有以下XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<A>
    <B>Dvortsovaya pl 2</B>
    <B>Inzhenernaya ul 4</B>
    <B>xyzul</B>
</A>

我想针对关键字列表测试<B>的内容(在这种情况下:'ul','pl','nab')并添加属性type='adress'如果有关键字存在。 所以预期的XML输出如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <A>
        <B type='adress'>Dvortsovaya pl 2</B>
        <B  type='adress'>Inzhenernaya ul 4</B>
        <B>xyzul</B>
    </A>

由于关键字列表可能会有所不同,我正在尝试编写一个普通的模板,它从变量中的列表中获取关键字。我尝试使用'循环'模板实现这一点,这显然不起作用:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>    

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

    <xsl:variable name="adressKeywords">
        <item n="1">ul</item>
        <item n="2">pl</item>
        <item n="3">nab</item>
    </xsl:variable>

    <xsl:template match="B">
        <xsl:call-template name="addAttribute">
            <xsl:with-param name="start" select="1"/>
            <xsl:with-param name="end" select="count($adressKeywords/item)"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="addAttribute">
        <xsl:param name="start"/>
        <xsl:param name="end"/>
        <xsl:variable name="text">
            <xsl:value-of select="normalize-space(.)"/>
        </xsl:variable>
        <xsl:if test="$start &lt;= $end">
            <xsl:variable name="reg">(^|\W)<xsl:value-of select="$adressKeywords/item[@n=$start]"
                />($|\W)</xsl:variable>
            <xsl:choose>
                <xsl:when test=" matches($text, $reg)">
                    <xsl:copy>
                        <xsl:attribute name="value">adress</xsl:attribute>
                        <xsl:apply-templates select="@*|node()"/>
                    </xsl:copy>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy>
                        <xsl:apply-templates select="@*|node()"/>
                    </xsl:copy>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:if>
            <xsl:if test="$start &lt;= $end">
                <xsl:call-template name="addAttribute">
                    <xsl:with-param name="start">
                        <xsl:value-of select="$start+1"/>
                    </xsl:with-param>
                    <xsl:with-param name="end">
                        <xsl:value-of select="$end"/>
                    </xsl:with-param>
                </xsl:call-template>
            </xsl:if>
    </xsl:template>
</xsl:stylesheet>

我知道怎样才能得到结果(如果可能的话......)? 谢谢!

2 个答案:

答案 0 :(得分:2)

我只是为那些匹配替代关键字的B元素编写模板:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>    

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

    <xsl:param name="adressKeywords">
        <item n="1">ul</item>
        <item n="2">pl</item>
        <item n="3">nab</item>
    </xsl:param>

    <xsl:variable name="regex" select="concat('(^|\W)(', string-join($adressKeywords/item, '|'), ')($|\W)')"/>

    <xsl:template match="B[matches(., $regex)]">
        <B type="address">
          <xsl:apply-templates select="@* | node()"/>
        </B>
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

使其更简单,为A / *添加模板,检查是否存在关键字并添加@type:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>    

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

<xsl:variable name="adressKeywords">
    <item>ul</item>
    <item>pl</item>
    <item>nab</item>
</xsl:variable>

<xsl:template match="/A">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>
<xsl:template match="A/*[true() = (for $var in $adressKeywords/* return if(contains(., $var)) then true() else false())]">
    <xsl:copy>
        <xsl:attribute name="type">adress</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>