顯示具有 XML 標籤的文章。 顯示所有文章
顯示具有 XML 標籤的文章。 顯示所有文章

2007年7月26日 星期四

Bursting Engine Implementation

其實這部份在一個月前就已經完成測試了
不過現在才有空寫上來

基本上
Tim的Blog提供的例子與架構已經很清楚了
但是習慣上會照著做一個不同的報表來用看看...
在做的過程中
才會知道有那些是重要的...要克服的問題..
否則看別人的Code...一切都是那麼理所當然...自己做看看才知道..即使只是模仿

我的測試分兩部份
第一部份是不管Data怎麼出來的部份...假設已有xml了
然後搭配JSP與Control file
看看有沒有什麼問題

如果第一部份沒問題
那麼第二部份的測試...就是把它完整地implement出來
從rdf開始..含report trigger..並掛到Server上跑
讓它完全如Tim的例子一樣運作完美...

(註:由於我用的是XMLP 5.6.2
所以要自己寫JCP..聽說5.6.3就不用了...)

第一部份:
* Control file : burst.xml 放到/tmp/下
* Data file : emp.xml 放到/tmp/下
* Rtf Template : test.rtf 放到/tmp/下
* JCP: BurstingTest.java compile後掛上Server..
主要在JCP中就會依Control file與Data去抓Template並做Bursting
因此測試時跑JCP就好

這邊卡住的問題有
1. JCP Compile問題
一開始抓下來的Java檔...居然在Compile時就有問題...
經過確認..
發現程式中用OADocumentProcessor是有問題的
http://forums.oracle.com/forums/thread.jspa?messageID=1843531
要使用DocumentProcessor

所以import的部份多加了
import oracle.apps.xdo.batch.DocumentProcessor;

程式中的這一段
lfile.writeln("Starting burst ...",1);
OADocumentProcessor dp = new OADocumentProcessor("/tmp/burst.xml","/tmp/emp.xml","/tmp");
lfile.writeln("Bursting initiated ... ",1);

也改為
file.writeln("Starting burst ...",1);
DocumentProcessor dp = new DocumentProcessor("/tmp/burst.xml","/tmp/emp.xml","/tmp");
lfile.writeln("Bursting initiated ... ",1);

2. Data file的問題
我的emp.xml中
用到幾個會有問題的tag...我用了EMP、EMPLOYEE、NAEM這類的....
結果在5.6.2中...不管我資料有幾筆...都只是Burst出第一筆...
這裡卡了很久
後來才知道可能是Bug
改了Tag後...就沒有問題了
http://forums.oracle.com/forums/message.jspa?messageID=1904432#1904432

這邊兩個問題都要感謝Ashish的協助

第二部份:
* Control file : burst.xml 放到/tmp/下
* Report file : BURSTDEMO.rdf 放到Server上
* Rtf Template : test.rtf 放到/tmp/下
* JCP: XMLPReportBurst.java compile後掛上Server..
主要是跑掛上Server的Report: BURSTDEMO..它產生的output就是XML格式
而由於它的After Report Trigger會去Call JCP
因此...JCP會抓得到它XML的output..加上Control file與template
一氣呵成完成後半部的Bursting動作

這部份與第一部份的差異
就在於怎麼去找到rdf的xml output
主要問題在
1. JCP怎麼寫
這邊沒有太大的麻煩..
Tim的例子本身就有這個功能..
只要傳入request id當參數就好...
甚至還能回過頭去改Request畫面上的Request Name...

2. RDF的After Report怎麼把自己的Request id當參數傳給JCP
這裡卡了一陣子
因為~~自己都還沒跑出去..要怎麼知道自己的Request id??
可以看這邊
http://zhxiangxie.blogspot.com/2007/06/how-to-get-this-request-id.html

而完成第一部份測試
加上克服第二部份的問題後
RDF到Bursting的路就走出來了

應該可以用來取代之前用JavaMail與iText寫的那一段功能...

2007年7月5日 星期四

Turning Rows into Columns

http://forums.oracle.com/forums/message.jspa?messageID=1921986#1921986

在這邊的討論
算是XMLP的進階應用...

然而感謝Anil Passi 的網站
介紹以xsl變數宣告模擬for loop的方式
才能應用到這的問題上

TEXT001{NO_IN_A_ROW}
TEXT002{INNER_GROUP}

---------------------------------------------------------------
| Attribute | Emp TEXT003{F} TEXT004{1} TEXT005{E} |
---------------------------------------------------------------
| Name | Emp TEXT003{F} TEXT006{Name} TEXT005{E} |
---------------------------------------------------------------
| Department | Emp TEXT003{F} TEXT007{DEPT} TEXT005{E} |
---------------------------------------------------------------
| Salary | Emp TEXT003{F} TEXT008{1000} TEXT005{E} |
---------------------------------------------------------------

TEXT005{E}


where TEXT004,TEXT005,TEXT006,TEXT007,TEXT008 are the same as the original document,
and

TEXT001: <xsl:variable name="no_in_a_row" select="number(5)"/>
TEXT002: <xsl:variable xdofo:ctx="incontext" name="inner_group" select=".//ROW"/>
<?for-each:$inner_group?><?if:(position()-1) mod $no_in_a_row=0?><xsl:variable name="first_rec" xdofo:ctx="incontext" select="position()"/>
TEXT003: <?for-each@cell:$inner_group[position()>=$first_rec and position() <$first_rec+$no_in_a_row]?>

2007年5月14日 星期一

BIP - dynamic grouping and calculating

一般會建議在D2K Report做Data的group與小計加總等
因為在D2K Report裡做這些事會比較簡單...
拉一拉就好了
但是...有幾個小小的缺點
1. 欠缺彈性.
D2K裡的group是固定的...以S/O銷售資料為例...
當拉了客戶別-產品-detail的group structure...
就無法輕易用於產品別-客戶-detail的group structure...
因此當有客戶別 /產品別 / 業務別 /地區別 ..各種報表...
則可能要寫四個...
但根本上的row data其實是一樣的...
2. 設定煩雜
D2K寫Data.. BIP做Template的方式...
至少都要多定義一個excutable來對應RDF檔..
承1..至少要多定義4個executable...
但如果sql只是簡單的抓row data..
則直接用data template的XML與XSD來做...
Concurrent program直接call XDODTEXE這支JCP就好了

因此..
當報表會因不同group條件而分支出多個子報表時
不妨用Data template抓row data...然而直接在RTF template上做動態的分組和加總就好

以下為幾個常用的技巧
假設資料為
<ROW>
<AAA> ... </AAA>
<BBB> ... </BBB>
<CCC> ... </CCC>
</ROW>
的架構
1. Dynamic Grouping
一般用 <?for-each?> ~ <?end for-each?> 只能抓取row data
需要用 <?for-each-group:ROW;AAA?> ~ <?end for-each-group?>
則可以對每一個不同的AAA做分組...

而對於分組內資料的取用..
則使用 <?for-each:current-group()?> ~ <?end for-each?>

假設要做巢式分組...AAA的組內還要依BBB再分
則這麼寫
------- <?for-each-group:ROW;AAA?>
---------------<?for-each-group:current-group();BBB?>
--------------------- <?for-each:current-group()?>
-----------------------------do some thing in current-group
--------------------- <?end for-each?>
---------------<?end for-each-group?>
------- <?end for-each-group?>


2. Group Calculating
在分組小計的時後
特別要注意的是...目前在第幾層
而原本的資料欄位都在ROW這一層
-------<?for-each-group:ROW;AAA?>
---------------<?for-each-group:current-group();BBB?>
--------------------- <?for-each:current-group()?>
-----------------------------do some thing in current-group
-----------------------------<?sum(current-group()//CCC)?> 加總AAA-BBB組內的CCC
--------------------- <?end for-each?>
---------------<?end for-each-group?>
---------------<?sum(current-group()/CCC)?> 加總AAA組內的CCC
------- <?end for-each-group?>

3. Powerful and Flexible-Variables
透過定義變數
<?xdoxslt:set_variable($_XDOCTX,'VAR_NM',VAR_Val)?>
指定變數
<?xdoxslt:set_variable($_XDOCTX,'VAR_NM',VAR_Val)?>
和呼叫變數
<?xdoxslt:get_variable($_XDOCTX,'VAR_NM')?>
可以輕易的做 grant total總計等運算

加上if等條件判斷式
也可以做條件換頁等動作

4. Page Break
一般而言
還是用<xsl:if xdofo:ctx="inblock" test="1=1"><xsl:attribute name="break-before">page</xsl:attribute></xsl:if>的語法就可以了

2007年3月21日 星期三

XMLP Transfer via FNDLOAD / XDOLoader

之前有記FNDLOAD由Test instance搬移資料到Prod instance的方式

然而XMLP的相關資料也可以做這樣的搬移
一樣可透過FNDLOAD

*DOWNLOAD
FNDLOAD apps/apps 0 Y DOWNLOAD
$XDO_TOP/patch/115/import/xdotmpl.lct XMLPData.ldt XDO_DS_DEFINITI
ONS
APPLICATION_SHORT_NAME=AR DATA_SOURCE_CODE=ARXCOBLX

TMPL_APP_SHORT_NAME=AR
{TEMPLATE_CODE=ARLETTER1}


*UPLOAD
FNDLOAD apps/apps 0 Y UPLOAD $XDO_TOP/patch/115/import/xdotmpl.lct XMLPData.ldt

另外可以透過XDOLoader
*DOWNLOAD
% java oracle.apps.xdo.oa.util.XDOLoader DOWNLOAD \
-DB_USERNAME \
-DB_PASSWORD \
-JDBC_CONNECTION \
-LOB_TYPE \
-APPS_SHORT_NAME \
-LOB_CODE \
-LANGUAGE \
-TERRITORY \
-LOG_FILE


*UPLOAD
% java oracle.apps.xdo.oa.util.XDOLoader UPLOAD \
-DB_USERNAME \
-DB_PASSWORD \
-JDBC_CONNECTION \
-LOB_TYPE \
-APPS_SHORT_NAME \
-LOB_CODE \
-LANGUAGE \
-TERRITORY \
-XDO_FILE_TYPE \
-NLS_LANG \
-FILE_CONTENT_TYPE \
-FILE_NAME \
-OWNER \
-CUSTOM_MODE [FORCENOFORCE] \
-LOG_FILE


詳細可再參考XMLP User Guide...

2007年3月9日 星期五

XMLP - How to do Page Break?

XMLP(XML Publisher)是導入R11i中發現非常好用的工具之一
目前應該稱它為BI Publisher吧
因為開發團隊的Blog已由XML Publisher Blog改為BI Publisher Blog了
現在已經到5.6.3版了..附在R12上..已成為R12上滿主要的一個引擎了

不過我還只是R11i的入門使用者
現在系統上還是5.0.0的...
上patch後可以到5.6.2吧...

以下記錄XMLP中進行跳頁的方式
主要參考自Oracle Forums兩篇討論

對目前一支需求報表
一張A4要印恰好兩個料
非常有幫助

[1]. 直接加page-break
< ?split-by-page-break:? >
但是無法搭配if ..(測試搭配if無效)
通常的用法是 < ?split-by-page-break:? > < ?end for-each? >
用於強制換頁

[2]. 使用xsl語法

<.xsl:if xdofo:ctx="inblock" test=$IF-Condition>
<.xsl:attribute name="break-before">page
<./xsl:attribute><./xsl:if>


例如每個G_ORDER_INFO section都換頁
<.xsl:if xdofo:ctx="inblock" test="position()<.count(//G_ORDER_INFO)">
<.xsl:attribute name="break-before">page<./xsl:attribute>
<./xsl:if>
或這個需求中...PAGE參數為偶數就換頁
<.xsl:if xdofo:ctx="inblock" test="PAGE mod 2=0">
<.xsl:attribute name="break-before">page<./xsl:attribute>
<./xsl:if>

XMLP的User Guide較基本...詳細的應用方法還是要自己由討論區與不斷測試來驗證..