2017-02-14 39 views
1

我想复制一个元素,但添加了一个新属性(@inTheList),其值标识名称位于给定列表上的属性。确定哪些元素的属性名称与列表匹配。将结果放入一个新属性

输入:

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

和列表[ “臂”, “鼻子”, “体”, “头”]不知何故表示。

输出:

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

有可能是一个聪明的XSLT十岁上下的方式做到这一点,但现在我甚至不能想象的暴力方式。

回答

1

假设XSLT 2.0,你可以在http://xsltransform.net/bFWR5EN使用

<?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> 

在线。

+0

这很好,但我想知道如果$ names有几十个或几百个项目会很慢。 $名称[。 =当前()/ @ * /名称()]扫描整个列表,即使没有更多的检查,对吧? – JPM

+0

它效果很好。没有性能问题。谢谢你,先生! – JPM

+0

那么,它确实会造成性能问题,将处理时间增加到2.5x。 – JPM

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

听起来像是你可以简单地做(假设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> 

您可能希望将此与标识转换模板一起使用。

相关问题