2011-01-15

XSLT 1.0处理分组

在处理一个接口映射时遇到需要分组的问题,因为发送方使用JDBC adapter从数据库抽取数据,SAP PI得到的数据结构为:
<row>
<column1/>
<column2/>
<column3/>
</row>
其中column1,column2,column3是JDBC adapter中SQL查询语句里select的表列。
这个问题通过graphic mapping的node function估计应该能解决,但没有例子和好的文档就先放弃了,改用XSLT来实现。现在读取出来的数据中有一列为INVOCIE_ID,同一个INVOICE下有多个line_item。为每一个INVOICE _ID应生成一个IDoc,所有具有相同INVOICE_ID的line_item要映射到同一个IDoc下。如果环境支持 XSLT 2.0,可以很方便的使用group-by解决分组的问题。试了一下SAP PI环境不支持group-by语句,只能使用XSLT 1.0支持的语句。一个名为Muenchian的方法颇为有名,使用了xsl:key语句和key函数,提高了XSLT处理分组的性能。一个简化的例子:
XML 源文件
<?xml version="1.0" encoding="UTF-8"?>
<MT_PTP_PURCHASEINVOICE>
    <row>
        <INVOICE_ID>12</INVOICE_ID>
        <INVOICE_CURRENCY>EUR</INVOICE_CURRENCY>
        <LINE_NUMBER>1</LINE_NUMBER>
    </row>
    <row>
        <INVOICE_ID>12</INVOICE_ID>
        <INVOICE_CURRENCY>EUR</INVOICE_CURRENCY>
        <LINE_NUMBER>2</LINE_NUMBER>
    </row>
    <row>
        <INVOICE_ID>13</INVOICE_ID>
        <INVOICE_CURRENCY>EUR</INVOICE_CURRENCY>
        <LINE_NUMBER>1</LINE_NUMBER>       
    </row>
   <row>
        <INVOICE_ID>13</INVOICE_ID>
        <INVOICE_CURRENCY>EUR</INVOICE_CURRENCY>
        <LINE_NUMBER>2</LINE_NUMBER>
    </row>
</MT_PTP_PURCHASEINVOICE>
XSLT 表单
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:key name="mykey" match="row" use="INVOICE_ID"/>
    <xsl:template match="/">
        <doc>
            <xsl:for-each select="//row[count(. | key('mykey', INVOICE_ID)[1]) = 1]">
                <xsl:sort select="INVOICE_ID"/>
                <invoice>
                    <INVOICE_ID>
                        <xsl:value-of select="INVOICE_ID"/>
                    </INVOICE_ID>
                    <items>
                        <xsl:for-each select="key('mykey', INVOICE_ID)">
                            <xsl:sort select="LINE_NUMBER"/>
                            <line>
                                <xsl:value-of select="LINE_NUMBER"/>
                            </line>
                        </xsl:for-each>
                    </items>
                </invoice>
            </xsl:for-each>
        </doc>
    </xsl:template>
</xsl:stylesheet>

没有评论:

发表评论