2014-07-09 119 views
0

我的xml如下所示。在此,數據庫中不存在少量itemName值。因此,我將檢查每個「itemName」值,如果數據庫中不存在任何值,則應在末尾顯示封閉的「order」節點。 這意味着所有'itemName'值都存在於數據庫中的所有'order'元素都必須先按順序顯示,剩下的所有'order'元素至少有一個'itemName'值不存在於數據庫必須移到最後。基於外部條件檢查的XSLT排序節點

<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「ABC」不存在於數據庫中,預期輸出是:

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

有人可以請提供關於如何進一步進行線索?非常感謝您的時間。

爲了更好地理解這個問題,我到目前爲止嘗試的代碼如下所示。此代碼將只將其itemName值不存在於數據庫中的一個「order」元素推送到文件末尾。我正在尋找所有這樣的「秩序」要素推到最後。模板'item-check-db'執行一個SQL,並根據數據庫中是否存在數據庫來返回'yes'或'no'。我使用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片段的最後一行沒有顯示在這裏。

+0

「*假設ITEMNAME「ABC '在數據庫中不存在*「這個假設如何傳遞給XSLT? –

+0

@ michael.hor257k說我有另一個xsl模板,它將itemName值作爲輸入,並執行任何需要的處理(如執行SQL或任何其他必要的操作)並返回'true'或'false'。 – Lokesh

+0

恐怕還不夠清楚。你爲什麼不告訴我們該模板(或其簡單的例子)? - 也指示XSLT 1.0或2.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> 
+0

@ micheal.hor257k兩個階段的處理節點是我在這裏需要的。另外通過添加一個額外的模板''我將在最終輸出中去掉這個中間屬性。非常感謝您的指導micheal.hor257k – Lokesh