XSLT:增量变量和参数分配

时间:2013-11-11 12:01:47

标签: variables xslt


你好

我需要以下xml

<Data>
    <Employees>
        <Employee>
            <EmployeeName>Ram</EmployeeName>
            <EmployeeID>123</EmployeeID>
            <Gender>M</Gender>
        </Employee>
        <Employee>
            <EmployeeName>Helen</EmployeeName>
            <EmployeeID>432</EmployeeID>
            <Gender>F</Gender>
        </Employee>
        <Employee>
            <EmployeeName>Dinesh</EmployeeName>
            <EmployeeID>321</EmployeeID>
            <Gender>M</Gender>
        </Employee>
    </Employees>
</Data>

转换为此

<?xml version="1.0" encoding="UTF-8"?>
<Employees>
    <Employee Gender="Male" Current="true" index="1">
        <Name>Ram</Name>
    </Employee>
    <Employee Gender="Male" Current="false" index="2">
        <Name>Dinesh</Name>
    </Employee>
    <Employee Gender="Female" Current="false" index="3">
        <Name>Helen</Name>
    </Employee>
</Employees>

我使用的样式表就是这个

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

                <xsl:for-each select="Employees/Employee[Gender = 'M']">
                <Employee Gender="Male">
                    <Name>
                        <xsl:value-of select="EmployeeName"/>
                    </Name>
                                </Employee>
                </xsl:for-each>
                <xsl:for-each select="Employees/Employee[Gender = 'F']">
                <Employee Gender="Female">
                    <Name>
                        <xsl:value-of select="EmployeeName"/>
                    </Name>
                                </Employee>
                </xsl:for-each>


        </Employees>
    </xsl:template>
</xsl:stylesheet>

我尝试使用过几个样本,但是没什么好看的。请问有人帮我吗?这只是我用来解释问题的示例代码。

或者更具体,

仅需要在第一个员工节点中设置“当前”。另一方面,索引应该在所有节点上。

2 个答案:

答案 0 :(得分:2)

您可以使用position()来确定元素在其父元素下的位置。我也倾向于重构模板以支持apply-templates,并为男性和女性干掉重复的员工映射。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
   <xsl:template match="Data">
      <Employees>
         <xsl:apply-templates select="Employees/Employee">
            <xsl:sort select="Gender" order="descending" />
         </xsl:apply-templates>
      </Employees>
   </xsl:template>

   <xsl:template match="Employee">
      <xsl:variable name="gender">
         <xsl:choose>
            <xsl:when test="Gender='M'">Male</xsl:when>
            <xsl:when test="Gender='F'">Female</xsl:when>
            <xsl:otherwise>Unknown</xsl:otherwise>
         </xsl:choose>
      </xsl:variable>
      <xsl:variable name="current">
         <xsl:choose>
            <xsl:when test="position() = 1">true</xsl:when>
            <xsl:otherwise>false</xsl:otherwise>
         </xsl:choose>
      </xsl:variable>
      <Employee Gender="{$gender}" Current="{$current}" index="{position()}">
            <Name>
               <xsl:value-of select="EmployeeName"/>
            </Name>
         </Employee>
   </xsl:template>
</xsl:stylesheet>

编辑根据@Ians解决方案,我添加了排序和Current属性。然而,我不确定复杂情况是什么 - 或许我错过了其他的东西?

答案 1 :(得分:1)

我只使用一个for-each(或者更可能是apply-templates,但我会按照您当前的结构进行操作),这样您就可以使用position()来生成索引。为了使所有Male员工首先加上Female员工,<xsl:sort> for-eachGender的降序排列就足够了(因为“M”后来在字母表中而不是“F”):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="Data">
        <Employees>
            <xsl:for-each select="Employees/Employee">
                <xsl:sort select="Gender" order="descending" />
                <Employee Gender="{Gender}" index="{position()}">
                    <xsl:attribute name="Current">
                        <xsl:choose>
                            <xsl:when test="position() = 1">true</xsl:when>
                            <xsl:otherwise>false</xsl:otherwise>
                        </xsl:choose>
                    </xsl:attribute>
                    <Name>
                        <xsl:value-of select="EmployeeName"/>
                    </Name>
                </Employee>
            </xsl:for-each>
        </Employees>
    </xsl:template>
</xsl:stylesheet>