2017-02-14 6 views
1

要素をコピーしますが、その要素に名前が指定された属性を識別する新しい属性(@inTheList)を追加します。リストに一致する要素の属性名を決定します。結果を新しい属性に置き換えます

入力:

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

何とか表さリスト[ "アーム"、 "鼻"、 "本文"、 "ヘッド"]。

出力:

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

あり、これを行うための巧妙なXSLTっぽい道は、おそらくですが、今私もブルートフォース方法を考えることはできません。このような入力を仮定し

答えて

1

あなたは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> 

Onlineを使用することができますXSLT 2.0と仮定すると。

+0

これはうれしいことですが、$名前に数十または数百のアイテムがある場合、遅くなるのだろうかと思います。 $ names [。 = current()/ @ */name()]はチェックする必要がなくなってもリスト全体をスキャンします。 – JPM

+0

それは素晴らしい仕事をした。パフォーマンスに問題はありません。ありがとうございます! – JPM

+0

実際、パフォーマンスの問題が発生し、処理時間が2.5倍に増えます。 – 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> 

恒等変換テンプレートと一緒に使用することをお勧めします。

関連する問題