XSLT基于外部条件检查订购节点

时间:2014-07-09 09:22:33

标签: xml xslt nodes

我的xml如下图所示。在这种情况下,数据库中几乎没有itemName值。因此,我会检查这些' itemName'值和数据库中是否存在任何值,封闭的顺序'节点应该显示在最后。 这意味着所有的订单'所有' itemName'数据库中存在的值必须首先按顺序显示,并且所有剩余的顺序必须按顺序显示。至少有一个' itemName'数据库中不存在的值必须移到最后。

<record>
<purchases>
    <purchase id="purchase_1">
        <customer>
            <FirstName>first</FirstName>
            <LastName>last</LastName>
        </customer>
    </purchase>
</purchases>
<orders>
    <order id="order_1">
            <item id="1111">
                <itemName>ABC</itemName>
            </item>
    </order>
    <order id="order_2">
            <item id="1111">
                <itemName>ABC</itemName>
            </item>
    </order>
    <order id="order_3">
            <item id="4444">
                <itemName>MNO</itemName>
            </item>
        </order>
</orders>

我可以从基于java的应用程序处理数据库上的这种情况检查。我试图通过从身份转换开始然后使用apply-templates来编写XSL代码,但我无法理解在调用apply-templates时如何执行数据库条件。我尝试了如下所示的内容,这是默认身份模板的补充:

<xsl:template match="/record/orders">
<xsl:apply-templates select="order[process all order elements whose condition check returns true]" />
<xsl:apply-templates select="order[process all order elements whose condition check returns false]" />

假设itemName&#39; ABC&#39;数据库中不存在,预期输出为:

<record>
<purchases>
    <purchase id="purchase_1">
        <customer>
            <FirstName>first</FirstName>
            <LastName>last</LastName>
        </customer>
    </purchase>
</purchases>
<orders>
    <order id="order_3">
            <item id="4444">
                <itemName>MNO</itemName>
            </item>
    </order>
    <order id="order_1">
            <item id="1111">
                <itemName>ABC</itemName>
            </item>
    </order>
    <order id="order_2">
            <item id="1111">
                <itemName>ABC</itemName>
            </item>
    </order>
</orders>

有人可以提供进一步处理的线索吗?非常感谢你的时间。

为了更好地理解问题,我到目前为止尝试的代码如下所示。此代码只会推送一个订单&#39; dataName值在数据库中不存在于文件末尾的元素。我正在寻找所有这样的订单&#39;元素被推到最后。模板&#39; item-check-db&#39;执行一个SQL并返回“是”&#39;或者没有&#39;取决于该项目是否存在于DB中。我使用xsl:import语句导入我的所有模板列表。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" version="1.0">

<xsl:template match="/">
    <xsl:variable name="exists" />
    <xsl:variable name="orderPos">
        <xsl:for-each select="/record/orders/order">
            <xsl:variable name="exists">
                <xsl:call-template name="item-check-db">
                    <xsl:with-param name="item" select="item/itemName" />
                </xsl:call-template>
            </xsl:variable>
            <xsl:if test="$exists = 'no'">
                <xsl:value-of select="position()" />
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:choose>
        <xsl:when test="string-length($orderPos) = 0">
            <xsl:apply-templates select="node() | @*" />
        </xsl:when>
        <xsl:otherwise>
            <xsl:apply-templates mode="alterOrders" select="node() | @*">
                <xsl:with-param name="lastOrderPos" select="$orderPos" />
            </xsl:apply-templates>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
</xsl:template>
<xsl:template match="node() | @*" mode="alterOrders">
    <xsl:param name="lastOrderPos" />
    <xsl:copy>
        <xsl:apply-templates mode="alterOrders" select="node() | @*">
            <xsl:with-param name="lastOrderPos" select="$lastOrderPos" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>
<xsl:template match="/record/orders" mode="alterOrders">
    <xsl:param name="lastOrderPos" />
    <xsl:copy>
        <xsl:apply-templates mode="alterOrders" select="order[not(position()=$lastOrderPos)]" />
        <xsl:apply-templates mode="alterOrders" select="order[position()=$lastOrderPos]" />
        <xsl:apply-templates mode="alterOrders" select="@*" />
    </xsl:copy>
</xsl:template>

我正在寻找XSLT 1.0解决方案。

*出于某种原因,我的代码或xml片段的最后一行没有显示在这里。

1 个答案:

答案 0 :(得分:0)

首先是:

您无法按不存在的属性对节点进行排序。需要通过调用模板确定的属性(在排序时)不存在。同样的事情也适用于您尝试使用谓词来区分节点。

因此,您需要分两个阶段处理节点:首先,将属性附加到每个节点,然后按该属性对结果节点集进行排序。

不幸的是,您没有向我们展示检查项目是否存在的模板。对于以下示例,我将提出一个:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="orders">
    <!-- first pass -->
    <xsl:variable name="orders">
        <xsl:apply-templates select="order" mode="first-pass"/>
    </xsl:variable>
    <!-- output -->
    <xsl:copy>
        <xsl:apply-templates select="exsl:node-set($orders)/order">
            <xsl:sort select="@exists" data-type="text" order="descending"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="order" mode="first-pass">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="exists">
            <xsl:call-template name="item-check-db">
                <xsl:with-param name="item" select="item/itemName" />
            </xsl:call-template>
        </xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template name="item-check-db">
    <xsl:param name="item"/>
    <xsl:value-of select="$item!='ABC'"/>
</xsl:template>

</xsl:stylesheet>

如果将以上内容应用于以下测试输入

<record>
    <purchases>
        <purchase id="purchase_1">
            <customer>
                <FirstName>first</FirstName>
                <LastName>last</LastName>
            </customer>
        </purchase>
    </purchases>
    <orders>
        <order id="order_1">
                <item id="111">
                    <itemName>ABC</itemName>
                </item>
        </order>
        <order id="order_2">
                <item id="222">
                    <itemName>DEF</itemName>
                </item>
        </order>
        <order id="order_3">
                <item id="111">
                    <itemName>ABC</itemName>
                </item>
            </order>
    </orders>
</record>

结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<record>
   <purchases>
      <purchase id="purchase_1">
         <customer>
            <FirstName>first</FirstName>
            <LastName>last</LastName>
         </customer>
      </purchase>
   </purchases>
   <orders>
      <order id="order_2" exists="true">
         <item id="222">
            <itemName>DEF</itemName>
         </item>
      </order>
      <order id="order_1" exists="false">
         <item id="111">
            <itemName>ABC</itemName>
         </item>
      </order>
      <order id="order_3" exists="false">
         <item id="111">
            <itemName>ABC</itemName>
         </item>
      </order>
   </orders>
</record>