使用XSLT生成用户名(比较节点)

时间:2015-03-17 17:50:12

标签: xml xslt duplicates unique transformation

这是我的要求:

Lastname是用户名,如果lastname相同则使用lastname + First initial,如果lastname + First initial相同则使用lastname + First initial + second letter first name。

我尝试使用密钥但我没有成功。(输入是一个包含人口统计数据的XML文档,总共可能有大约1200条记录,需要比较此XML文件中的姓氏并根据条件生成用户名如上所述)。 这是我的第一个问题,请让我知道你需要回答的信息。

我可以使用XSLT 1.0或2.0

以下是XML示例:

<XML>
<Data>
        <First_Name>Chris</First_Name>
        <Middle_Name>E</Middle_Name>
        <Last_Name>Kyle</Last_Name>
        <Employee_ID>100</Employee_ID>
</Data>
<Data>
        <First_Name>Allen</First_Name>
        <Middle_Name></Middle_Name>
        <Last_Name>Kyle</Last_Name>
        <Employee_ID>101</Employee_ID>
</Data>
<Data>
        <First_Name>Aron</First_Name>
        <Middle_Name></Middle_Name>
        <Last_Name>Kyle</Last_Name>
        <Employee_ID>102</Employee_ID>
</Data>
<Data>
        <First_Name>Luffy</First_Name>
        <Middle_Name>D</Middle_Name>
        <Last_Name>Monkey</Last_Name>
        <Employee_ID>103</Employee_ID>
</Data>
<XML>

对于转换后的这个例子,我应该得到如下的用户名: 1)Kylec 2)Kyleal 3)Kylear 4)猴

这是我的部分工作的XSLT(有多个更改,但目前卡在这里)

   <xsl:template match="/">
            <xsl:call-template name="HeaderRecord"/>

            <xsl:for-each select="//XML/Data[generate-id(.)= generate-id(key('ELN',Last_Name)[1])]">
            <xsl:sort select="Last_Name" order="ascending"/>
            <xsl:for-each select="key('ELN',Last_Name)">

                <xsl:if test="position()=0">
                    <xsl:call-template name="DataRecords"/>
                </xsl:if>

                <xsl:if test="position()=1">
                    <xsl:for-each select="//XML/Data[generate-id(.)= generate-id(key('EFN1',substring(First_Name,1,1))[1])]">
                        <xsl:for-each select="key('EFN1',substring(First_Name,1,1))">
                            <xsl:sort select="First_Name" order="ascending"/>
                            <xsl:if test="position()=0">
                            <xsl:call-template name="DuplicateDataRecords"/>
                            </xsl:if>
                            <xsl:if test="position()=1">
                            <xsl:call-template name="DuplicateDataRecords2"/>
                             </xsl:if>
                         </xsl:for-each>
                      </xsl:for-each>  
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

谢谢!

1 个答案:

答案 0 :(得分:1)

您可以在检查现有名称时为每个条件定义单独的键;仅适用于Last_NameLast_NameFirst_Name的第一个字母,Last_Name的abd加上First_Name的前两个字母

<xsl:key name="ELN" match="Data" use="Last_Name" />
<xsl:key name="EFN1" match="Data" use="concat(Last_Name, substring(First_Name,1,1))" />
<xsl:key name="EFN2" match="Data" use="concat(Last_Name, substring(First_Name,1,2))" />

然后,你可以有一个匹配Data的模板,其中有xsl:choose依次使用键测试所有条件。

因此,要检查这是Last_Name的第一次出现(并使用姓氏作为用户名),请执行此操作

<xsl:when 
     test="generate-id(.)= generate-id(key('ELN',Last_Name)[1])">

下一个xsl:when将测试Last_Name + First_Name的第一个字符,但它还必须检查此组合在任何地方都不是有效Last_Name

<xsl:when 
     test="generate-id(.)= generate-id(key('EFN1',concat(Last_Name, substring(First_Name,1,1)))[1])
           and not(key('ELN', concat(Last_Name, substring(First_Name,1,1))))">

同样,检查First_Name

的前两个字符
<xsl:when 
     test="generate-id(.)= generate-id(key('EFN2',concat(Last_Name, substring(First_Name,1,2)))[1])
           and not(key('EFN1', concat(Last_Name, substring(First_Name,1,2))))
           and not(key('ELN', concat(Last_Name, substring(First_Name,1,2))))">

试试这个XSLT ......

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

    <xsl:key name="ELN" match="Data" use="Last_Name" />
    <xsl:key name="EFN1" match="Data" use="concat(Last_Name, substring(First_Name,1,1))" />
    <xsl:key name="EFN2" match="Data" use="concat(Last_Name, substring(First_Name,1,2))" />

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

    <xsl:template match="Data">
        <User_Name>
        <xsl:choose>
            <xsl:when test="generate-id(.)= generate-id(key('ELN',Last_Name)[1])">
                <xsl:value-of select="Last_Name" />
            </xsl:when>
            <xsl:when test="generate-id(.)= generate-id(key('EFN1',concat(Last_Name, substring(First_Name,1,1)))[1])
                            and not(key('ELN', concat(Last_Name, substring(First_Name,1,1))))">
                <xsl:value-of select="concat(Last_Name, substring(First_Name,1,1))" />
            </xsl:when>
            <xsl:when test="generate-id(.)= generate-id(key('EFN2',concat(Last_Name, substring(First_Name,1,2)))[1])
                            and not(key('EFN1', concat(Last_Name, substring(First_Name,1,2))))
                            and not(key('ELN', concat(Last_Name, substring(First_Name,1,2))))">
                <xsl:value-of select="concat(Last_Name, substring(First_Name,1,2))" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:variable name="username" select="concat(Last_Name, substring(First_Name,1,2))" />
                <xsl:value-of select="$username" />
                <xsl:value-of select="count(preceding-sibling::Data[concat(Last_Name, substring(First_Name,1,2)) = $username]) + 1" />
            </xsl:otherwise>
        </xsl:choose>
        </User_Name>
    </xsl:template>
</xsl:stylesheet>

请注意,如果Last_Name + First_Name的前两个字母不是唯一的,我使用的后退是在用户名的末尾附加一个数字。