XSLT按深节点排序

时间:2014-06-10 07:39:15

标签: xml sorting xslt

是否可以按比当前节点更深层次的节点进行排序?

我有一个xml文件我在一个表示产品结构的html表中。 我想对' Part ERP CostSet'中的sct_cst_tot值进行排序。项目

我无法使用正确排序 我试过了,但无法找到解决方案。

TOP LEVEL ASSEMBLY的子项目将按sct_cst_tot

排序
  • 6340.70
  • 7040.30

NEXT LEVEL ASSEMBLY 1的子项目将按sct_cst_tot排序

  • 400.00
  • 600.00

这是xml文件

<?xml version="1.0" encoding="utf-8"?>
<Result>
    <Item type="Part">
        <name>TOP LEVEL ASSEMBLY</name>
        <item_number>TLA1</item_number>
        <Relationships>
            <Item type="Part ERP CostSet">
                <sct_cst_tot>14205.1513157895</sct_cst_tot>
            </Item>
            <Item type="Part BOM">
                <quantity>4</quantity>
                <related_id>
                    <Item type="Part">
                        <name>NEXT LEVEL ASSEMBLY 1</name>
                        <item_number>NLA1</item_number>
                        <Relationships>
                            <Item type="Part ERP CostSet">
                                <sct_cst_tot>7040.3000000000</sct_cst_tot>
                            </Item>
                            <Item type="Part BOM">
                                <quantity>1</quantity>
                                <related_id>
                                    <Item type="Part">
                                        <name>COMPONENT 2</name>
                                        <item_number>ICN-0002</item_number>
                                        <Relationships>
                                            <Item type="Part ERP CostSet">
                                                <sct_cst_tot>600.00</sct_cst_tot>
                                            </Item>
                                        </Relationships>
                                    </Item>
                                </related_id>
                            </Item>
                            <Item type="Part BOM">
                                <quantity>3</quantity>
                                <related_id>
                                    <Item type="Part">
                                        <name>COMPONENT 3</name>
                                        <item_number>ICN-0003</item_number>
                                        <Relationships>
                                            <Item type="Part ERP CostSet">
                                                <sct_cst_tot>400.0000000000</sct_cst_tot>
                                            </Item>
                                        </Relationships>
                                    </Item>
                                </related_id>
                            </Item>
                        </Relationships>
                    </Item>
                </related_id>
            </Item>
            <Item type="Part BOM">
                <quantity>2</quantity>
                <related_id>
                    <Item type="Part">
                        <name>NEXT LEVEL ASSEMBLY 2 </name>
                        <item_number>NLA2</item_number>
                        <Relationships>
                            <Item type="Part ERP CostSet">
                                <sct_cst_tot>6340.6999997988</sct_cst_tot>
                            </Item>
                        </Relationships>
                    </Item>
                </related_id>
            </Item>
        </Relationships>
    </Item>
    <BOM>10</BOM>
</Result>

这是xsl文件

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:aras="http://www.aras-corp.com">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:template match="/">
        <table style="width: 98%; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
            <thead>
                <tr>
                    <th>0</th>
                    <th>1</th>
                    <th>2</th>
                    <th>3</th>
                    <th>4</th>
                    <th>5</th>
                    <th>6</th>
                    <th>7</th>
                    <th>Part Number</th>
                    <th>Name</th>
                    <th>Quantity</th>
                    <th>Single Unit Cost</th>
                </tr>
            </thead>
            <xsl:call-template name="Levels"></xsl:call-template>
        </table>
    </xsl:template>
    <xsl:template name="Levels">
        <tbody>
            <xsl:for-each select="//Item[@type='Part']">
                <xsl:variable name="Depth" select="count(ancestor::Item[@type='Part'])"></xsl:variable>
                <tr>
                    <!--Method to visual show where the item sits in the BOM hierarchy-->
                    <xsl:call-template name="IndentLevel">
                        <xsl:with-param name="Depth" select="$Depth" />
                    </xsl:call-template>
                    <td>
                        <xsl:value-of select="item_number"></xsl:value-of>
                    </td>
                    <td>
                        <xsl:value-of select="name"></xsl:value-of>
                    </td>
                    <xsl:apply-templates select=".">
                        <xsl:with-param name="Depth" select="count(ancestor::Item[@type='Part'])"></xsl:with-param>
                    </xsl:apply-templates>
                </tr>
            </xsl:for-each>
        </tbody>
    </xsl:template>
    <xsl:template name="IndentLevel">
        <xsl:param name="Depth" />
        <td>
            <xsl:if test="$Depth=0">0</xsl:if>
        </td>
        <td>
            <xsl:if test="$Depth=1">1</xsl:if>
        </td>
        <td>
            <xsl:if test="$Depth=2">2</xsl:if>
        </td>
        <td>
            <xsl:if test="$Depth=3">3</xsl:if>
        </td>
        <td>
            <xsl:if test="$Depth=4">4</xsl:if>
        </td>
        <td>
            <xsl:if test="$Depth=5">5</xsl:if>
        </td>
        <td>
            <xsl:if test="$Depth=6">6</xsl:if>
        </td>
        <td>
            <xsl:if test="$Depth=7">7</xsl:if>
        </td>
    </xsl:template>
    <xsl:template match="Item[@type='Part']">
        <xsl:param name="Depth"></xsl:param>
        <!--Quantity-->
        <td>
            <xsl:choose>
                <!--Top level Quantity is always 1-->
                <xsl:when test="$Depth = '0'">1</xsl:when>
                <xsl:when test="../../quantity != '0'">
                    <xsl:value-of select="../../quantity"></xsl:value-of>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </td>
        <td>
            <xsl:value-of select="format-number(Relationships/Item[@type='Part ERP CostSet']/sct_cst_tot,&quot;###,###,##0.00&quot;)"></xsl:value-of>
        </td>
    </xsl:template>
</xsl:stylesheet>

这是当前输出(注意级别可能无法正确汇总到下一个值)

+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
|0|1|2|3|4|5|6|7|PartNumber |Name                   |Single Unit Cost   |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
|0| | | | | | | |TLA1       |TOP LEVEL ASSEMBLY     |14,205.15          |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
| |1| | | | | | |NLA1       |NEXT LEVEL ASSEMBLY 1  |7,040.30           |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
| | |2| | | | | |ICN-0002   |COMPONENT 2            |600.00             |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
| | |2| | | | | |ICN-0003   |COMPONENT 3            |400.00             |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
| |1| | | | | | |NLA2       |NEXT LEVEL ASSEMBLY 2  |6,340.70           |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+

这是所需的输出

+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
|0|1|2|3|4|5|6|7|PartNumber |Name                   |Single Unit Cost   |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
|0| | | | | | | |TLA1       |TOP LEVEL ASSEMBLY     |14,205.15          |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
| |1| | | | | | |NLA2       |NEXT LEVEL ASSEMBLY 2  |6,340.70           |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
| |1| | | | | | |NLA1       |NEXT LEVEL ASSEMBLY 1  |7,040.30           |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
| | |2| | | | | |ICN-0003   |COMPONENT 3            |400.00             |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+
| | |2| | | | | |ICN-0002   |COMPONENT 2            |600.00             |
+-+-+-+-+-+-+-+-+-----------+-----------------------+-------------------+

编辑以简化xml输出

1 个答案:

答案 0 :(得分:0)

通过最小化,我指的是你的XML和你的XSLT。这是XSLT的一个示例,除了按其后代的sct_cst_tot值对项目进行排序之外什么都不做。

如果我理解正确,您需要将该值乘以数量,但我无法穿透确定数量的逻辑。

在任何情况下,XSLT都不允许按变量排序 - 因此,如果您想按扩展成本排序并在表格单元格中显示它,则需要计算两次。

XSLT 1.0

<?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="/">
    <table border="1">
        <xsl:for-each select="//Item[@type='Part']">
        <xsl:sort select="Relationships/Item[@type='Part ERP CostSet']/sct_cst_tot" data-type="number" order="ascending"/>
            <tr>
                <td><xsl:value-of select="name" /></td>
                <td><xsl:value-of select="Relationships/Item[@type='Part ERP CostSet']/sct_cst_tot" /></td>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

</xsl:stylesheet>

编辑:

我不确定它是否巧合,但我已经设法通过向您的&#34;级别&#34;添加以下两个排序说明来获取所请求的订单。模板:

<xsl:template name="Levels">
    <tbody>
        <xsl:for-each select="//Item[@type='Part']">

        <!-- sort by depth -->
        <xsl:sort select="count(ancestor::Item[@type='Part'])" data-type="number" order="ascending"/>
        <!-- sort by cost -->
        <xsl:sort select="Relationships/Item[@type='Part ERP CostSet']/sct_cst_tot" data-type="number" order="ascending"/>

            <xsl:variable name="Depth" select="count(ancestor::Item[@type='Part'])"></xsl:variable>
            <tr>
            ....

编辑2:

  

这是零件物料清单的关系   (related_id / Item [@type =&#39; Part&#39;] / Relationships / Item [@type =&#39; Part ERP   CostSet&#39;] / sct_cst_tot)。产品(或物料清单)结构   应始终保持。即在上面的例子中,ICN-0002和   ICN-0003是&#39;孩子&#39; NLA1,所以应该直接   在NLA1下,就像NLA1和NLA2是TLA1的孩子一样

如果我理解这一点,这不是(仅)一个排序问题,而是按层次顺序处理节点 - 只有兄弟姐妹按成本排序。

这意味着你不能滥杀滥伤:

<xsl:for-each select="//Item[@type='Part']">

相反,您必须从顶部开始,并告诉每个部件依次处理其子部件。请尝试以下骨架样式表:

<?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="/Result">
    <table border="1">
        <thead>
            <tr>
                <th>Part Number</th>
                <th>Name</th>
                <th>Single Unit Cost</th>
            </tr>
        </thead>
        <tbody>
            <xsl:apply-templates select="Item[@type='Part']">
                <xsl:sort select="Relationships/Item[@type='Part ERP CostSet']/sct_cst_tot" data-type="number" order="ascending"/>
            </xsl:apply-templates>
        </tbody>
     </table>
</xsl:template>

<xsl:template match="Item[@type='Part']">
    <tr>
        <td><xsl:value-of select="item_number"/></td>
        <td><xsl:value-of select="name" /></td>
        <td><xsl:value-of select="Relationships/Item[@type='Part ERP CostSet']/sct_cst_tot" /></td>
    </tr>
    <xsl:apply-templates select="Relationships/Item[@type='Part BOM']/related_id/Item[@type='Part']">
        <xsl:sort select="Relationships/Item[@type='Part ERP CostSet']/sct_cst_tot" data-type="number" order="ascending"/>
    </xsl:apply-templates>
</xsl:template>

</xsl:stylesheet>