1

我一直在尝试为以下文档编写样式表,它可以检查所有用户的奖励并将该用户的名称作为子元素添加到 /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>

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

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

提前致谢

4

1 回答 1

1

This transformation:

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

when applied on the provided XML 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-->
        </award>
        <award>
            <name>Award B</name>
        </award>
    </awards>
</document>

produces (what I guess should be) the wanted, correct result:

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

Explanation: Proper use of keys and overriding the identity rule.

UPDATE: The OP has shown the actually wanted output format. This is very close to what I guessed. The only modification is to use this template, insted the one in the initial solution:

 <xsl:template match="user" mode="inclusion">
  <user identity="{@identity}">
    <xsl:copy-of select="concat(name/first, ' ', name/last)"/>
  </user>
 </xsl:template>
于 2012-05-28T15:25:33.477 回答