确定哪个元素的属性名称与列表匹配。将结果放入新属性

时间:2017-02-14 01:05:46

标签: xslt

我想复制一个元素,但是添加一个新属性(@inTheList),其值标识名称在给定列表中的属性。

输入:

<element head="this" body="that" foot="the other">

和列表[“arm”,“nose”,“body”,“head”]以某种方式表示。

输出:

<element head="this" body="that" foot="the other" inTheList="head body">

可能有一种聪明的XSLT方法可以做到这一点,但是现在我甚至无法想到一种蛮力的方式。

3 个答案:

答案 0 :(得分:1)

假设输入如下:

<root>
    <element head="this" nose="whatever" body="that" foot="the other"/>
    <element arm="this" body="that" foot="the other"/>
    <element foot="that"/>
</root>

然后这个模板会做你想要的(评论中的解释):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes"/>

    <!-- Change this to match the elements you need to update -->
    <xsl:template match="/">
        <out>
            <xsl:apply-templates select="root/element"/>
        </out>
    </xsl:template>

    <!-- copy an "element" and add a "theList" attribute listing selected attributes that are present -->
    <xsl:template match="element">
        <!-- This variable selects the target attributes -->
        <xsl:variable name="names">
            <xsl:apply-templates select="@arm|@nose|@body|@head"/>
        </xsl:variable>
        <xsl:copy>
            <!-- copy all attributes -->
            <xsl:copy-of select="@*"/>
            <!-- add the new attribute if any of the target names are present -->
            <xsl:if test="$names != ''">
                <xsl:attribute name="theList">
                    <xsl:value-of select="normalize-space($names)"/>
                </xsl:attribute>
            </xsl:if>
        </xsl:copy>
    </xsl:template>

    <!-- attribute name + a space separator -->
    <xsl:template match="element/@*">
        <xsl:value-of select="concat(name(), ' ')"/>
    </xsl:template>

</xsl:stylesheet>

输出:

<out>
    <element head="this"
             nose="whatever"
             body="that"
             foot="the other"
             theList="head nose body"/>
    <element arm="this" body="that" foot="the other" theList="arm body"/>
    <element foot="that"/>
</out>

答案 1 :(得分:1)

听起来你可以简单地做(假设XSLT 1.0):

<xsl:template match="element">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:attribute name="theList">
            <xsl:for-each select="@head | @body | @arm | @nose">
                <xsl:value-of select="name()"/>
                <xsl:if test="position() != last()">
                    <xsl:text> </xsl:text>
                </xsl:if>
            </xsl:for-each>
        </xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

您可能希望将此与 identity transform 模板一起使用。

答案 2 :(得分:1)

假设您使用XSLT 2.0

<?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" exclude-result-prefixes="xs">

    <xsl:param name="names" as="xs:string*" select='"arm", "nose", "body", "head"'/>

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

    <xsl:template match="*[@*/name() = $names]">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="inTheList" select="$names[. = current()/@*/name()]"/>
        </xsl:copy>
    </xsl:template>
</xsl:transform>

http://xsltransform.net/bFWR5EN在线。

相关问题