我想复制一个元素,但是添加一个新属性(@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方法可以做到这一点,但是现在我甚至无法想到一种蛮力的方式。
答案 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>