使用xslt创建具有公共元素的元素列表

时间:2012-05-28 14:58:48

标签: xml xslt xpath

我一直在尝试为以下文档编写一个样式表,可以检查所有用户的奖励,并将该用户的名称添加为/ awards / award元素的子元素

<document>
    <users>
        <user identity="1">
            <name>
                <first>abc</first>
                <last>xyz</last>
            </name>
            <achievements>
                <achievement>Award A</achievement>
                <achievement>Award B</achievement>
            </achievements>
        </user>
        <user identity="2">
            <name>
                <first>123</first>
                <last>DEF</last>
            </name>
            <achievements>
                <received>Award A</received>
            </achievements>
        </user>
        <user identity = "3">
            <name>
                <first>aaa</first>
                <last>bbb</last>
            </name>
            <achievements>
                <received>Award B</received>
            </achievements>
        </user>
    </users>
    <!--awards-->
    <awards>
        <award>
            <name>Award A</name>
            <!--here the list of the users who recieved this award has to be included-->
        </award>
        <award>
            <name>Award B</name>
        </award>
    </awards>
</document>

我写下了以下不完整的样式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="awards/award">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
                <!--how can i create a list of all users who have this award-->
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

我无法弄清楚在模板“奖励/奖励”中编写查询的方式,例如“将所有已获得此奖项的用户添加为名为user的子元素,并将添加元素的值添加为用户“并给出以下输出。如果有人能引导我采用正确的方法,我将非常感激。

<document>
    <users>
        <user identity="1">
            <name>
                <first>abc</first>
                <last>xyz</last>
            </name>
            <achievements>
                <achievement>Award A</achievement>
                <achievement>Award B</achievement>
            </achievements>
        </user>
        <user identity="2">
            <name>
                <first>123</first>
                <last>DEF</last>
            </name>
            <achievements>
                <received>Award A</received>
            </achievements>
        </user>
        <user identity="3">
            <name>
                <first>aaa</first>
                <last>bbb</last>
            </name>
            <achievements>
                <received>Award B</received>
            </achievements>
        </user>
    </users>
    <!--awards-->
    <awards>
        <award>
            <name>Award A</name>
            <user identity="1">abc xyz</user>
            <user identity="2">123 DEF</user>    
        </award>
        <award>
            <name>Award B</name>
            <user identity="1">abc xyz</user>
            <user identity="3">aaa bbb</user>
        </award>
    </awards>
</document>

提前致谢

1 个答案:

答案 0 :(得分:1)

此转化

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kUserByAward" match="user"
          use="achievements/*[self::achievement or self::received]"/>

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

 <xsl:template match="award">
   <award>
    <xsl:apply-templates select="node()"/>
    <xsl:apply-templates select="key('kUserByAward', name)" mode="inclusion"/>
   </award>
 </xsl:template>

 <xsl:template match="user" mode="inclusion">
  <user>
    <xsl:copy-of select="name"/>
  </user>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<document>
    <users>
        <user>
            <name>
                <first>abc</first>
                <last>xyz</last>
            </name>
            <achievements>
                <achievement>Award A</achievement>
                <achievement>Award B</achievement>
            </achievements>
        </user>
        <user>
            <name>
                <first>dsd</first>
                <last>sdasdsadsa</last>
            </name>
            <achievements>
                <received>Award A</received>
            </achievements>
        </user>
        <user>
            <name>
                <first>aaa</first>
                <last>bbb</last>
            </name>
            <achievements>
                <received>Award B</received>
            </achievements>
        </user>
    </users>
    <!--awards-->
    <awards>
        <award>
            <name>Award A</name>
            <!--here the list of the users who recieved this award has to be included-->
        </award>
        <award>
            <name>Award B</name>
        </award>
    </awards>
</document>

产生(我猜测应该是什么)想要的正确结果

<document>
   <users>
      <user>
         <name>
            <first>abc</first>
            <last>xyz</last>
         </name>
         <achievements>
            <achievement>Award A</achievement>
            <achievement>Award B</achievement>
         </achievements>
      </user>
      <user>
         <name>
            <first>dsd</first>
            <last>sdasdsadsa</last>
         </name>
         <achievements>
            <received>Award A</received>
         </achievements>
      </user>
      <user>
         <name>
            <first>aaa</first>
            <last>bbb</last>
         </name>
         <achievements>
            <received>Award B</received>
         </achievements>
      </user>
   </users><!--awards-->
   <awards>
      <award>
         <name>Award A</name><!--here the list of the users who recieved this award has to be included-->
         <user>
            <name>
               <first>abc</first>
               <last>xyz</last>
            </name>
         </user>
         <user>
            <name>
               <first>dsd</first>
               <last>sdasdsadsa</last>
            </name>
         </user>
      </award>
      <award>
         <name>Award B</name>
         <user>
            <name>
               <first>abc</first>
               <last>xyz</last>
            </name>
         </user>
         <user>
            <name>
               <first>aaa</first>
               <last>bbb</last>
            </name>
         </user>
      </award>
   </awards>
</document>

解释:正确使用 keys 并覆盖 identity rule

更新:OP已显示实际需要的输出格式。这与我猜测的非常接近。唯一的修改是使用此模板,在初始解决方案中输入一个:

 <xsl:template match="user" mode="inclusion">
  <user identity="{@identity}">
    <xsl:copy-of select="concat(name/first, ' ', name/last)"/>
  </user>
 </xsl:template>