"加入" XSLT

时间:2015-05-04 11:18:21

标签: xml xslt

如果符合某些条件,我需要在会计系统中向用户发出警告。

下面是我的XML片段,非常简洁,仅显示相关部分:

<DATA>
    <ACCOUNTING>
        <POSTINGS>
            <POSTING KEY="815" ID="PR0">
                    ...
                <EXPENSE_TYPE_ID NAME="Expense Type ABC">123456</EXPENSE_TYPE_ID> 
                <AMOUNT>40000</AMOUNT> 
                    ...
            </POSTING>
        </POSTINGS>
        <LINES>
            <LINE KEY="1450" POSTING="PR0">
                    ...
                <BOOKKEEPING_TYPE>D</BOOKKEEPING_TYPE> 
                <ACCOUNT_ID NAME="Debit Account Name HHHH">112233</ACCOUNT_ID> 
                <AMOUNT>40000</AMOUNT> 
                <DESCRIPTION>Expense Type ABC</DESCRIPTION> 
                <SPECIALS_TYPE_A>1</SPECIALS_TYPE_A> 
                    ...
            </LINE>
            <LINE KEY="1451" POSTING="PR0">
                    ...
                <BOOKKEEPING_TYPE>C</BOOKKEEPING_TYPE> 
                <ACCOUNT_ID NAME="Credit Account Name TTTT">987654</ACCOUNT_ID> 
                <AMOUNT>-40000</AMOUNT> 
                <DESCRIPTION>Expense Type ABC</DESCRIPTION> 
                <SPECIALS_TYPE_A>1</SPECIALS_TYPE_A> 
                    ...
            </LINE>
        </LINES>
    </ACCOUNTING>
</DATA>

必须根据以下标准显示消息:

  1. 个别发布行的金额必须超过20,000
  2. 必须使用值&#39; 1&#39;
  3. 初始化特殊类型
  4. 帐户名称不得包含“税务帐户”字样
  5. 发布行必须是借记簿记类型
  6. 所选费用类型列表已与发布行
  7. 一起使用

    以下是我当前的实现,在&#34; normal&#34;例:

    <xsl:variable name="AmountWarningLower" select="20000" />
    <xsl:for-each select="ACCCOUNTING/LINES/LINE[
        DESCRIPTION = 'Expense Type ABC' or 
        DESCRIPTION = 'Expense Type DEF' or 
            ...
        ]">
        <xsl:if test="(SPECIALS_TYPE_A = '1') and 
            (AMOUNT &gt; $AmountWarningLower) and 
            not(contains(ACCOUNT_ID/@NAME,'Tax Account')) 
            and not(BOOKKEEPING_TYPE='C')">
    
            //Print message
            //Print message
    
        </xsl:if>
    </xsl:for-each>
    

    目前,我已经通过一长串OR来解决了要求#5,以匹配发布行的描述。

    这并不理想,因为客户可以选择更改费用类型的描述,这将破坏我的解决方案。

    但是因为应用程序在Line实体中不包含费用类型ID,所以我无法直接映射它们。

    反之亦然,该应用程序在过帐实体中不包含特殊类型信息。

    我看到&#34; Posting Record ID&#34;中的行之间存在关键匹配,即。 &#34; PR0&#34;

    &#34; KEY&#34;两者之间没有直接联系。

    我有什么方法可以加入&#34;两个XML实体,通过匹配&#34;发布记录ID&#34;,即。 &#34; PR0&#34;,然后更新我的解决方案以匹配来自过帐实体的费用类型ID,而不是来自Line实体的行描述?

    理想情况如下:

    <xsl:for-each select="ACCCOUNTING/LINES/LINE[
        @EXPENSE_TYPE_ID = '123456' or 
        @EXPENSE_TYPE_ID = '789123' or 
            ...
        ]">
    

    希望这是有道理的,也是可能的。

    提前感谢您帮助找到解决方案。

1 个答案:

答案 0 :(得分:0)

  

我需要在XML实体之间进行交叉引用,作为不同的部分   信息列在不同的实体中。

密钥的作用:首先,您定义查找的实体和密钥值:

<xsl:key name="postings-by-id" match="POSTING" use="ID" />

现在,每次使用值为&#34; PRO&#34;时,它都将解决具有匹配ID值的POSTING节点 - 例如,您可以执行以下操作:

<xsl:for-each select="ACCCOUNTING/LINES/LINE">
    <xsl:variable name="posting-code" select="key('postings-by-id', @POSTING)/@KEY" />
    ...

编辑:

由于在定义变量之前无法使用变量,并且对键的重复引用会很麻烦,因此在您的情况下反转键操作的方向可能更方便。

考虑以下简化示例:

<强> XML

<root>
    <categories>
        <category id="501" name="red"/>
        <category id="502" name="green"/>
        <category id="503" name="blue"/>
    </categories>
    <items>
        <item id="1" category="red"/>
        <item id="2" category="blue"/>
        <item id="3" category="green"/>
        <item id="4" category="blue"/>
        <item id="5" category="red"/>
        <item id="6" category="green"/>
        <item id="7" category="blue"/>
        <item id="8" category="red"/>
        <item id="8" category="green"/>
        <item id="9" category="blue"/>
    </items>
</root>

在这里,我们希望只选择&#34;绿色&#34;中的项目。或者&#34;蓝色&#34;类别 - 但要使用类别id值&#34; 502&#34;和&#34; 503&#34;。

XSLT 1.0

<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:key name="item-by-category" match="item" use="@category" />

<xsl:template match="/root">
    <xsl:copy>
        <xsl:for-each select="key('item-by-category', categories/category[@id ='502' or @id ='503']/@name)">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

<强>结果

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <item id="2" category="blue"/>
   <item id="3" category="green"/>
   <item id="4" category="blue"/>
   <item id="6" category="green"/>
   <item id="7" category="blue"/>
   <item id="8" category="green"/>
   <item id="9" category="blue"/>
</root>