我的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片段的最后一行没有显示在这里。
答案 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>