2015年12月 4日 (金)

OTHER_XMLの中身

JPOUG Advent Calendar 2015 - 4日目のエントリーです。

役に立たないから、絶対最後まで読まないでね!!! (^^)

さて、
みなさん、マニュアル読んでますか? 
最近は量が多いので、必要になってから、なりそうだから読むことが多いです。
Oracle® Databaseリファレンス 12cリリース1 (12.1) なんて特にそうです。
ただ、一度読み始めると、いろいろと気づくところもあるわけです...こんな情報が取れるのか! とか。


あ〜、これは、禁断のw マニュアルに記載されてないパラメータを指定すると見れるやつだ!!! とか気づくこともあったり。

例えば、V$SQL_PLANDBA_HIST_SQL_PLANのOTHER_XML列。

この列の説明には実に興味深いことが書かれています。以下の説明、読んでてワクワクしますw 
何が格納されているのでしょう???(もう、みんな知ってるくせに〜)

”アウトライン・データ(同じ計画の再作成に使用できる一連のオプティマイザ・ヒント)”

見たくないですか? 中身。

見たいですよね。私もそうです!


ただ、OTHER_XML列、列名の通り、CLOB型で中身はXMLです!!!
SQL*Plusで普通に表示しようとすると長すぎて読みにくいってのが難点w


ならばXMLにも対応しているSQL文で何とかしてみたいと思います。

ゴニョゴニョ、パタパタ。

できました。

dba_hist_sql_plan向けですが。(v$sql_planビューでも同様のことができます!)
(注:dba_hist_*ビューを参照するにはOracle Diagnostics Packが必要でっす。ですが、v$sql_planを参照するのならオプションはいらないですよね.)

こんな感じです

SYSTEM> !cat report_outline_hints.sql
col outline for a200
set linesize 300
set pagesize 10000
set veri off

SELECT '/*+' AS outline FROM DUAL
UNION ALL
SELECT ' '||'BEGIN_OUTLINE_DATA' FROM DUAL
UNION ALL
SELECT
' '||o.outlinehint
FROM
(
SELECT
EXTRACTVALUE(
VALUE(x)
, '/hint/text()'
) AS outlinehint
FROM
XMLTABLE(
'/*/outline_data/hint'
PASSING(
SELECT
XMLTYPE(other_xml)
FROM
dba_hist_sql_plan
WHERE
other_xml IS NOT NULL
AND sql_id = '&1'
AND plan_hash_value = &2
)
) x
) o
UNION ALL
SELECT ' '||'END_OUTLINE_DATA' FROM DUAL
UNION ALL
SELECT '*/' FROM DUAL
/
set veri on

実行すると以下のような、:) 情報を取り出すことができます!!

SYSTEM> @report_outline_hints gdtyuqcyk8x1c 2236229349

OUTLINE
------------------------------------------------------------------------------------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
DB_VERSION('12.1.0.2')
ALL_ROWS
OUTLINE_LEAF(@"SEL$2")
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "B"@"SEL$1" ("ILM_EXECUTION$"."EXECUTION_ID"))
NO_ACCESS(@"SEL$1" "A"@"SEL$1")
LEADING(@"SEL$1" "B"@"SEL$1" "A"@"SEL$1")
USE_MERGE(@"SEL$1" "A"@"SEL$1")
PQ_FILTER(@"SEL$1" SERIAL)
INDEX(@"SEL$2" "A"@"SEL$2" ("ILM_EXECUTION$"."EXECUTION_ID"))
FULL(@"SEL$2" "B"@"SEL$2")
LEADING(@"SEL$2" "A"@"SEL$2" "B"@"SEL$2")
USE_MERGE(@"SEL$2" "B"@"SEL$2")
USE_HASH_AGGREGATION(@"SEL$2")
END_OUTLINE_DATA
*/

表示された内容に、身に覚え、
いや、見覚えのある方も多いことと思います :) あれでね。そう、あれです。
マニュアルに記載されいないパラメータを利用しなくても取り出せるんです。

ついでなので、マニュアルに記載のないパラメータを使ったDBMS_XPLAN.DISPLAY_AWRで同じ情報をリストしてみました。DBMS_XPLAN.DISPLAY_AWR以外のDISPLAY*関数のformatパラメータでもできます:)
(注: DISPLAY_AWRでAWRを参照するのでOracle Diagnostics Packが必要でっす。 ですが、DISPLAY_CURSOR(),DISPLAY()とDISPLAY_PLAN()ならAWRは参照しないのでオプションはいらないですよね。)

PROMPT
PROMPT ****** display_awr with outline option *********
SELECT
plan_table_output as outline
FROM
TABLE(DBMS_XPLAN.DISPLAY_AWR(sql_id=>'&1',plan_hash_value=>&2,format=>'OUTLINE'))
/


****** DBMS_XPLAN.DISPLAY_AWR with OUTLINE option *******

OUTLINE
------------------------------------------------------------------------------------------
SQL_ID gdtyuqcyk8x1c
--------------------
SELECT B.EXECUTION_ID, NVL(A.N_COUNT,0), A.COMP_TIME FROM ( SELECT
A.EXECUTION_ID, COUNT(*) N_COUNT, NVL(MAX(B.COMPLETION_TIME), SYSDATE)
COMP_TIME FROM SYS.ILM_EXECUTION$ A, SYS.ILM_RESULTS$ B WHERE
EXECUTION_STATE = :B7 AND A.EXECUTION_ID = B.EXECUTION_ID AND
B.JOB_STATUS NOT IN (:B6 , :B5 , :B4 , :B3 , :B2 , :B1 ) GROUP BY
A.EXECUTION_ID )A, ILM_EXECUTION$ B WHERE B.EXECUTION_ID =
A.EXECUTION_ID (+) AND EXECUTION_STATE = :B7 AND (ROWNUM <= :B9 OR :B9
= :B8 )

Plan hash value: 2236229349

-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 4 (100)| |
| 1 | COUNT | | | | | |
| 2 | FILTER | | | | | |
| 3 | MERGE JOIN OUTER | | 1 | 65 | 4 (50)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID | ILM_EXECUTION$ | 1 | 26 | 0 (0)| |
| 5 | INDEX FULL SCAN | PK_TASKID | 1 | | 0 (0)| |
| 6 | SORT JOIN | | 1 | 39 | 4 (50)| 00:00:01 |
| 7 | VIEW | | 1 | 39 | 3 (34)| 00:00:01 |
| 8 | HASH GROUP BY | | 1 | 65 | 3 (34)| 00:00:01 |
| 9 | MERGE JOIN | | 1 | 65 | 3 (34)| 00:00:01 |
| 10 | TABLE ACCESS BY INDEX ROWID| ILM_EXECUTION$ | 1 | 26 | 0 (0)| |
| 11 | INDEX FULL SCAN | PK_TASKID | 1 | | 0 (0)| |
| 12 | SORT JOIN | | 1 | 39 | 3 (34)| 00:00:01 |
| 13 | TABLE ACCESS FULL | ILM_RESULTS$ | 1 | 39 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------

Outline Data
-------------

/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
DB_VERSION('12.1.0.2')
ALL_ROWS
OUTLINE_LEAF(@"SEL$2")
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "B"@"SEL$1" ("ILM_EXECUTION$"."EXECUTION_ID"))
NO_ACCESS(@"SEL$1" "A"@"SEL$1")
LEADING(@"SEL$1" "B"@"SEL$1" "A"@"SEL$1")
USE_MERGE(@"SEL$1" "A"@"SEL$1")
PQ_FILTER(@"SEL$1" SERIAL)
INDEX(@"SEL$2" "A"@"SEL$2" ("ILM_EXECUTION$"."EXECUTION_ID"))
FULL(@"SEL$2" "B"@"SEL$2")
LEADING(@"SEL$2" "A"@"SEL$2" "B"@"SEL$2")
USE_MERGE(@"SEL$2" "B"@"SEL$2")
USE_HASH_AGGREGATION(@"SEL$2")
END_OUTLINE_DATA
*/

ちなみに、11g R2でも動作します!


どうでしたか?役に立たなかったですよね?
以上、OUTLINE HINTSより愛を込めてお送りしました!


参考: (日本語で書かれたエントリーは見当たらない。初か、もしかして!w)

Oracle SQL Plan Stability
http://blog.tanelpoder.com/oracle/performance/sql/oracle-sql-plan-stability/


Plan stability in 10g - using existing cursors to create Stored Outlines and SQL profiles
http://oracle-randolf.blogspot.jp/2009/03/plan-stability-in-10g-using-existing.html


FORCE_MATCH for Stored Outlines and/or SQL Baselines????? – follow up
https://tonyhasler.wordpress.com/2011/12/

How to hint – 1
https://jonathanlewis.wordpress.com/2011/06/08/how-to-hint-1/

dbms_xplan(3)
https://jonathanlewis.wordpress.com/2008/03/06/dbms_xplan3/



追記:

@yoshikawさんに指摘され、EXTRACTVALUE()が11.2で非推奨になっていたとことに気づく orz.

@yoshikawさん、指摘ありがとうございます。 

XMLTABLE().... COLUMNSを使えばEXTRACTVALUE()はいらなかった!!!! ということでEXTRACTVALUEなし版も作りました!!

ただ、CON_IDも見ないとマルチテナントに対応できず、エラーになると気づいたが、
11gにも対応しようとすると、もう一工夫必要なことに気づき、再び、orz.

つづきは、...いずれ...

変更したSQL文は以下のとおり。

SYSTEM> !cat report_outline_hints.sql
col outline for a200
set linesize 300
set pagesize 10000
set veri off

SELECT '/*+' AS outline FROM dual
UNION ALL
SELECT ' '||'BEGIN_OUTLINE_DATA' FROM DUAL
UNION ALL
SELECT
' '||x.outline_hint
FROM
XMLTABLE(
'/*/outline_data/hint/text()'
PASSING(
SELECT
XMLTYPE(other_xml)
FROM
dba_hist_sql_plan
WHERE
other_xml IS NOT NULL
AND sql_id = '&1'
AND plan_hash_value = &2
)
COLUMNS outline_hint PATH '/text()'
) x
UNION ALL
SELECT ' '||'END_OUTLINE_DATA' FROM DUAL
UNION ALL
SELECT '*/' FROM DUAL
/

SYSTEM> @report_outline_hints gdtyuqcyk8x1c 2236229349

OUTLINE
--------------------------------------------------------------------------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
DB_VERSION('12.1.0.2')
ALL_ROWS
OUTLINE_LEAF(@"SEL$2")
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "B"@"SEL$1" ("ILM_EXECUTION$"."EXECUTION_ID"))
NO_ACCESS(@"SEL$1" "A"@"SEL$1")
LEADING(@"SEL$1" "B"@"SEL$1" "A"@"SEL$1")
USE_MERGE(@"SEL$1" "A"@"SEL$1")
PQ_FILTER(@"SEL$1" SERIAL)
INDEX(@"SEL$2" "A"@"SEL$2" ("ILM_EXECUTION$"."EXECUTION_ID"))
FULL(@"SEL$2" "B"@"SEL$2")
LEADING(@"SEL$2" "A"@"SEL$2" "B"@"SEL$2")
USE_MERGE(@"SEL$2" "B"@"SEL$2")
USE_HASH_AGGREGATION(@"SEL$2")
END_OUTLINE_DATA
*/

JPOUG Advent Calendar 2015、12/5は、Yohei Azekatsu さんです。どんな変態ネタが飛び出すのか、乞うご期待!!

| | コメント (0) | トラックバック (0)

2009年9月19日 (土)

Modeling Forum 2009

昨日は2年ぶりにModeling Forum 2009へ。
いつも思うんですが10,000円のイベントが事前登録で無料ってのがいいっす。:)
全てのセッションは無理だったので最終セッション「Facilitated Requirements Workshops : Collaborating to Define Needs」/Ellen Gottesdienerを聴講。尚、このセッションを含めたいくつかのセッションはModeling Forum 2009のサイトで配信される予定だそうです。(10月初旬予定)
ということ聴講できなかった方も聴講した方は再確認ということでまた楽しめそうです。

ファシリテートされたワークショップ:力を合わせてニーズを定義するというタイトルでしたがそのワークショップの中心的な役割を果たすのが「ファシリテーター」。短いセッションでしたが「ファシリテーター」の重要な役割は、参加者が上手くコラボレーションできるような状態へ導くというところがポイントのように思いました。

最後に恒例のようになった著書販売+サイン会までは時間の都合で無理でしたが。最近の著書は以下。。そう言えば2年前はレベッカ・ワークスブラックさんのサイン会でサインしてもらってたっけ。。


| | コメント (0) | トラックバック (0)

2008年3月 7日 (金)

Oracle de XMLDB #26 - XMLTYPEの更新

OTN-Jで、PL/SQLでXMLTYPEのあるの要素の値を変更したり、ある要素の値を参照したいというスレッドがあったのでレスしておいた。

そういえば、XQueryやXPathを使ったOracle XMLDBネタもやっているが更新系のはやってないな(というかまだ、XMLの更新、追加、削除に関する標準が定まっていないわけだから仕方ない。)

ということで、前述したOTN-Jのネタをもう少しフラッシュアップして?!(for updateなどが抜けていたので。。)残しておく事にした。

まず、hogehoge表に以下のようなXMLを登録する。

SCOTT> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SCOTT>
SCOTT> desc hogehoge
名前 NULL? 型
----------------------------------------- -------- ----------------------------
SEQNO NOT NULL NUMBER
XMLINFO XMLTYPE

SCOTT>
SCOTT> insert into hogehoge values(1,xmltype('<?xml version="1.0"?><addressbook>
<person id="1"><name>岡田</name><age>30</age>
<address zipcode="123456">東京都ホゲ市ホゲ町1−1</address></person><person id="2">
<name>安倍</name><age>50</age>
<address zipcode="1050011">東京都ホゲ区ホゲ田町1−1−1</address>
</person></addressbook>'));

1行が作成されました。

SCOTT> commit;

コミットが完了しました。

SCOTT>
SCOTT>
SCOTT> set timi on
SCOTT> set long 4000
SCOTT> col xmlinfo for a80
SCOTT> set linesize 132
SCOTT> set pagesize 1000
SCOTT> select * from hogehoge where seqno=1;

SEQNO XMLINFO
---------- ------------------------------------------------------------
1 <?xml version="1.0"?><addressbook><person id="1"><name>岡田<
/name><age>30</age><address zipcode="123456">東京都ホゲ市ホ
ゲ町1−1</address></person><person id="2"><name>安倍</name>
<age>50</age><address zipcode="1050011">東京都ホゲ区ホゲ田
町1−1−1</address></person></addressbook>


経過: 00:00:00.01
SCOTT>

上記のようなXML文書を対象に特定のid属性値を持つperson要素に含まれるname要素の値を変更するストアドファンクション。
(もうすこし平たく言うと、指定した名前を変更するストアドファンクション。略し過ぎか・・・)

XML文書の変更方法は他にもあるが、PL/SQLパッケージで行うにはDOM APIであるDBMS_XMLDOMパッケージを利用して行う。
尚、XMLTYPEをDBMS_XMLDOMパッケージで更新する際のポイントは、XMLTYPEインスタンスからDOMインスタンスを生成し、DOMインスタンに対して必要な更新操作行った上で、XMLTYPEインスタンスを表へ書き戻すという所。(該当部分は赤太字にしてあります。)

SCOTT> l
1 create or replace
2 function changePersonName
3 (
4 iKey in number,
5 iPersonId in varchar2,
6 iNewName in varchar2
7 ) return xmltype
8 is
9 xml xmlType;
10 personNodeList dbms_xmldom.DomNodeList;
11 personNode dbms_xmldom.DomNode;
12 nameNodeList dbms_xmldom.DomNodeList;
13 personAttrNodeMap dbms_xmldom.DomNamedNodeMap;
14 idAttrNode dbms_xmldom.DomNode;
15 wKey number;
16 wPersonId varchar2(38);
17 wNewName varchar2(60);
18 begin
19 wKey := iKey;
20 wPersonId := iPersonId;
21 wNewName := iNewName;
22
23 select xmlinfo into xml from hogehoge where seqno = wKey for update;
24
25 personNodeList := dbms_xmldom.getElementsByTagName(
26 dbms_xmldom.newDomDocument(xml)
27 ,'person'
28 );
29
30 if not dbms_xmldom.isNull(personNodeList) then
31 for i in 0..dbms_xmldom.getLength(personNodeList) loop
32 personNode := dbms_xmldom.item(personNodeList, i);
33 personAttrNodeMap := dbms_xmldom.getAttributes(personNode);
34 idAttrNode := dbms_xmldom.getNamedItem(personAttrNodeMap, 'id');
35 if dbms_xmldom.getNodeValue(idAttrNode) = wPersonId then
36 nameNodeList := dbms_xmldom.getChildrenByTagName(
37 dbms_xmldom.makeElement(personNode)
38 ,'name'
39 );
40 dbms_xmldom.setNodeValue(
41 dbms_xmldom.getFirstChild(dbms_xmldom.item(nameNodeList, 0))
42 ,wNewName
43 );
44 update hogehoge set xmlinfo = xml where seqno = wKey;
45 exit;
46 end if;
47 end loop;
48 end if;
49 return xml;
50* end;
SCOTT> /

ファンクションが作成されました。

経過: 00:00:00.04
SCOTT>
SCOTT>
SCOTT>
SCOTT> l
1 declare
2 xml xmlType;
3 begin
4 xml := changePersonName(1, '1', '福田ほげ蔵');
6 commit;
7* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.03
SCOTT>
SCOTT>
SCOTT> select * from hogehoge where seqno=1;
SEQNO XMLINFO
---------- --------------------------------------------------------------------------------
1 <?xml version="1.0"?>
<addressbook>
<person id="1">
<name>福田ほげ蔵</name>
<age>30</age>
<address zipcode="123456">東京都ホゲ市ホゲ町1−1</address>
</person>
<person id="2">
<name>安倍</name>
<age>50</age>
<address zipcode="1050011">東京都ホゲ区ホゲ田町1−1−1</address>
</person>
</addressbook>


経過: 00:00:00.00
SCOTT>

もうお気づきだと思うが、Oracle11gでも発生しているこちらからは操作できないところでwhitespaceが追加されたり、されなかったりする。まあこれ自体は大抵の場合問題にはならないのだが。。

あともうひとつの話題は特定の要素の値を取り出したいということ。これだけならDBMS_XMLDOMパッケージを使わなくても、SQL/XMLを使えば簡単ですよね。
XMLQuery()関数を使って、id属性値が "1"であるperson要素以下にあるage要素の値を参照する例です。

SCOTT> set linesize 80
SCOTT> l
1 select
2 xmlquery(
3 'let $n := $xmldoc//person[@id="1"]/age/text()
4 return $n'
5 passing by value xmlinfo as "xmldoc"
6 returning content
7 ) as "age"
8* from hogehoge where seqno=1
SCOTT> /

age
--------------------------------------------------------------------------------
30

経過: 00:00:00.04
SCOTT>

ちなみに、Oracleのマニュアルは以下の辺りを参照するとよいと思いますが、DOM、XQueryやXPathに関してはXML関連のサイトもググって調べたほうがよいと思います。XMLの操作の基本を理解していれば、あとはどんなツールを使ってそれを行うかということだけですから。

マニュアル
Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス 10g R2 - DBMS_XMLDOM
Oracle Database SQLリファレンス 10g R2 - XMLQUERY

Enjoy!

| | コメント (0) | トラックバック (0)

2008年2月21日 (木)

Oracle de XMLDB #25 - Relational dataをXMLへ #7のおまけ

1つ忘れていました。

何故、「Relational dataをXMLへ」というネタを取り上げようと思ったのか?

それはOTN-Jのこのスレに回答したことがきっかけだった。OTN-JのスレのネタはMacOSX環境下ではないのだけれど、Oracle XML DBを調べていたこともあり、その次いでに Eclipse for MacOSXではどうなるのか単純に知りたかっただけだった。そしてその準備段階のネタがMacOSXのEclipseを日本語化という記事だった。

ということで、前回はJDeveloperを使って試したことを書いた。今回はおまけとして、

Eclipse 3.3.1.1 for MacOSX(日本語化済み)

NetBeans IDE 6.0.1 for MacOSX

でやってみた。。(ただそれだけなんですけど・・・・)

利用したOracle JDBCドライバなどは前々回の記事を参照してください。

どれを使っても同じ結果にはなるのですが・・・・NetBeans6.0.1は随分といい感じに仕上がっているように感じた。(^^

Eclipse_s

Eclipse


Netbeans_s

Netbeans

| | コメント (0) | トラックバック (0)

Oracle de XMLDB #25 - Relational dataをXMLへ #7のおまけ

1つ忘れていました。

何故、「Relational dataをXMLへ」というネタを取り上げようと思ったのか?

それはOTN-Jのこのスレに回答したことがきっかけだった。OTN-JのスレのネタはMacOSX環境下ではないのだけれど、Oracle XML DBを調べていたこともあり、その次いでに Eclipse for MacOSXではどうなるのか単純に知りたかっただけだった。そしてその準備段階のネタがMacOSXのEclipseを日本語化という記事だった。

ということで、前回はJDeveloperを使って試したことを書いた。今回はおまけとして、

Eclipse 3.3.1.1 for MacOSX(日本語化済み)

NetBeans IDE 6.0.1 for MacOSX

でやってみた。。(ただそれだけなんですけど・・・・)

利用したOracle JDBCドライバなどは前々回の記事を参照してください。

どれを使っても同じ結果にはなるのですが・・・・NetBeans6.0.1は随分といい感じに仕上がっているように感じた。(^^

Eclipse_s

Eclipse


Netbeans_s

Netbeans

| | コメント (0) | トラックバック (0)

Oracle de XMLDB #24 - Relational dataをXMLへ #7

リレーショナルデータをXMLへ変換するシリーズもひとまず最終回ということで、最後は、Oracleデータベース側でXMLTypeインスタンスへ変換して、クライアントではXMLTypeインスタンスを受け取るだけの例を一つ。
環境は前回の記事を見てもらうとして早速試してみる。

Xmldb24_project Xmldb24_project_property


バックナンバー:
Oracle de XMLDB #18 - Relational dataをXMLへ #1
Oracle de XMLDB #19 - Relational dataをXMLへ #2
Oracle de XMLDB #20 - Relational dataをXMLへ #3
Oracle de XMLDB #21 - Relational dataをXMLへ #4
Oracle de XMLDB #22 - Relational dataをXMLへ #5
Oracle de XMLDB #23 - Relational dataをXMLへ #6

以下の例は、SQL/XMLとOracleが提供しているXQuery関数 ora:view()を利用し、リレーショナルデータからXMLTypeインスタンスを作るまでをOracleデータベース側で行い、クライアントではXMLTypeインスタンスを受け取るだけというもの。

package jp.macdeoracle.sample;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import oracle.jdbc.OracleResultSet;
import oracle.jdbc.pool.OracleDataSource;

import oracle.xdb.XMLType;


public class Table2Xml2
{
public Table2Xml2()
throws SQLException
{
OracleDataSource ods;
ods = new OracleDataSource();
ods.setURL(
"jdbc:oracle:thin:scott/tiger@192.168.1.20:1521:lampeye"
);

Connection conn = ods.getConnection();
Statement stmt = conn.createStatement();
OracleResultSet rs = (OracleResultSet)stmt.executeQuery(
"SELECT "
+ "XMLROOT("
+ "XMLQuery("
+ "'<ROWSET> {"
+ " for $d in ora:view(\"EMP\") "
+ " order by $d"
+ " return $d"
+ "} </ROWSET>'"
+ "RETURNING CONTENT), VERSION '1.0') "
+ "FROM dual"
);
DatabaseMetaData meta = conn.getMetaData();
System.out.println(meta.getDatabaseProductVersion());
System.out.println(meta.getDriverName()+":"+meta.getDriverVersion());
while(rs.next()) {
System.out.println(
"=======================\n"
+((XMLType)rs.getObject(1)).getStringVal()
);
}
rs.close();
stmt.close();
conn.close();
}

public static void main(String[] args) throws SQLException
{
Table2Xml2 dbXml = new Table2Xml2();
}
}


実行結果は以下の通り。

Oracle Database 11g Release 11.1.0.0.0 - Production
Oracle JDBC driver:10.1.0.3.0
=======================
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>1980-12-17</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-02-20</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-02-22</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-04-02</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-09-28</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-05-01</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-06-09</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>1981-11-17</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-09-08</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-12-03</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>1981-12-03</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>1982-01-23</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>2008-01-01</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
</ROWSET>

プロセスが終了コード0で終了しました。


いろいろな方法があるので悩みそうな気もするなぁ。。。。やっぱり。。。

| | コメント (0) | トラックバック (0)

2008年2月20日 (水)

Oracle de XMLDB #23 - Relational dataをXMLへ #6

さて、Oracleデータベース側だけでリレーショナルデータをXMLTypeインスタンスへ変換する方法は一通り試したので、今度はリレーショナルデータを取り出しクライアント側でXMLへ変換してみた。
接続するOracleデータベースはいままで通り、Oracle11g R1 EE 11.1.0.6.0 for Linux(x86)なのだが、クライアントとして利用するMacOSX 10.4.11の構成は多少異なるので以下に示しておく。

Jdeveloper1013png

IDE : Oracle JDeveloper10g Studio Edition 10.1.3.0.4 for MacOSX
Oracle XML Developer's Kit(XDK) for Java - 10.2.0.2.0 Linux Production
JDBCドライバ : Oracle Instant Client for MacOSX(PPC) 10.1.0.3.0付属の ojdbc14.jar
Oracle XML Parser : JDeveloper 10g Studio Edition for MacOSX version 10.1.3.0.4に付属するOracle XML Parser v2 (xmlparserv2.jar)
Oracle XML SQL Utility : JDeveloper 10g Studio Edition for MacOSX version 10.1.3.0.4に付属するOracle XML SQL Utiliry (xsu12.jar)

Xmldb23_project Xmldb23_project_property


バックナンバー:
Oracle de XMLDB #18 - Relational dataをXMLへ #1
Oracle de XMLDB #19 - Relational dataをXMLへ #2
Oracle de XMLDB #20 - Relational dataをXMLへ #3
Oracle de XMLDB #21 - Relational dataをXMLへ #4
Oracle de XMLDB #22 - Relational dataをXMLへ #5

以下の例では、emp表をempno順にソートして読み込み、Oracle XML SQL Utilityを利用して読み込んだResultsetからXMLへ変換。

package jp.macdeoracle.sample;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import oracle.jdbc.pool.OracleDataSource;

import oracle.xml.sql.query.OracleXMLQuery;

public class Table2Xml1
{
public Table2Xml1()
throws SQLException
{
OracleDataSource ods;
ods = new OracleDataSource();
ods.setURL(
"jdbc:oracle:thin:scott/tiger@192.168.1.20:1521:lampeye"
);

Connection conn = ods.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from emp order by empno");
OracleXMLQuery xmlqry = new OracleXMLQuery(conn, rs);

String xmlString = xmlqry.getXMLString();
DatabaseMetaData meta = conn.getMetaData();
System.out.println(meta.getDatabaseProductVersion());
System.out.println(meta.getDriverName()+":"+meta.getDriverVersion());
System.out.println("=====================\n"+xmlString);
rs.close();
stmt.close();
conn.close();
}

public static void main(String[] args) throws SQLException
{
Table2Xml1 Table2Xml1 = new Table2Xml1();
}
}


出力結果は以下の通り。ROW要素にnum属性がある以外、データベース側だけで変換した場合と内容的には変らない。
データベースサーバ側で変換まで行うか、クライアント側で変換するか、どちらが良いかといういうより、どのように負荷分散するかという戦略に合わせて考えればいいんじゃないかと思う。

Oracle Database 11g Release 11.1.0.0.0 - Production
Oracle JDBC driver:10.1.0.3.0
=====================
<?xml version = '1.0'?>
<ROWSET>
<ROW num="1">
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>12/17/1980 0:0:0</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW num="2">
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>2/20/1981 0:0:0</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW num="3">
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>2/22/1981 0:0:0</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW num="4">
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>4/2/1981 0:0:0</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW num="5">
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>9/28/1981 0:0:0</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW num="6">
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>5/1/1981 0:0:0</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW num="7">
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>6/9/1981 0:0:0</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW num="8">
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>11/17/1981 0:0:0</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW num="9">
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>9/8/1981 0:0:0</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW num="10">
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>12/3/1981 0:0:0</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW num="11">
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>12/3/1981 0:0:0</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW num="12">
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>1/23/1982 0:0:0</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW num="13">
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>1/1/2008 0:0:0</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
</ROWSET>

プロセスが終了コード0で終了しました。

次回は、データベース側でXMLへの変換まで行いクライアント側ではその結果を受け取るだけの例を一つ。

| | コメント (0) | トラックバック (0)

2008年2月19日 (火)

Oracle de XMLDB #22 - Relational dataをXMLへ #5

リレーショナルデータを取り出してからXMLへ変換する方法へ行く前にもう一つあるのを忘れてました。
SYS_XMLAGG()XMLELEMENT()XMLFOREST()関数を利用する方法。
Oracle9i R1から提供されていた関数だったが、古くから提供されていたので完璧に忘れてました。m(_ _)m
(マニュアルを調べた上でOracle9i R1から提供されていた関数と書いたが・・・もし、Oracle8i 8.1.7あたりからあったよ!というツッコミがあればご遠慮なく。)


バックナンバー:
Oracle de XMLDB #18 - Relational dataをXMLへ #1
Oracle de XMLDB #19 - Relational dataをXMLへ #2
Oracle de XMLDB #20 - Relational dataをXMLへ #3
Oracle de XMLDB #21 - Relational dataをXMLへ #4

2008/2/19 9:0:0
文字参照のミスを修正しました。


尚、他のXQueryの結果に関してはいままでもこちらでは制御できない改行が挿入された結果だったり、逆に取り除かれた結果が返されたりしていたが、前述の関数を利用した場合は全体に整形用改行が入るのではなく、SYS_XMLAGG()関数でマージされたXMLELEMENT()の結果からは改行は取り除かれているが、XML宣言やルート要素タグの後には何故か改行が付加される。(要素間の改行やインデントなどは目視する際に見やすくするためなので、あっても無くていいのだが、なんとも気持ちの悪い付け方をしてくれる。。。)

また、いままで実行してきた各SQL文は、それぞれ2回実行してからalter system flush shared_poolを1度実行した後に実行してある。(実行環境は以前と同じ

SQL*Plus: Release 10.1.0.3.0 - Production on 火 2月 19 00:00:09 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

> conn scott/tiger@lampeye
接続されました。
SCOTT> set long 4000
SCOTT> set pagesize 1000
SCOTT> select
2 sys_xmlagg(
3 xmlelement("ROW",
4 xmlforest(
5 empno,
6 ename,
7 job,
8 mgr,
9 hiredate,
10 sal,
11 comm,
12 deptno
13 ))) xmldoc
14 from
15 emp
16 order by
17 empno;

XMLDOC
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<ROWSET>
<ROW><EMPNO>9999</EMPNO><ENAME>ほげ</ENAME><JOB>ENGINEER</JOB><MGR>7566</MGR><HI
REDATE>2008-01-01</HIREDATE><SAL>2500</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>
7369</EMPNO><ENAME>SMITH</ENAME><JOB>CLERK</JOB><MGR>7902</MGR><HIREDATE>1980-12
-17</HIREDATE><SAL>800</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>7499</EMPNO><EN
AME>ALLEN</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-02-20</HIREDAT
E><SAL>1600</SAL><COMM>300</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>7521</EMPN
O><ENAME>WARD</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-02-22</HIR
EDATE><SAL>1250</SAL><COMM>500</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>7566</
EMPNO><ENAME>JONES</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981-04-02<
/HIREDATE><SAL>2975</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>7654</EMPNO><ENAME
>MARTIN</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-09-28</HIREDATE>
<SAL>1250</SAL><COMM>1400</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>7698</EMPNO
><ENAME>BLAKE</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981-05-01</HIRE
DATE><SAL>2850</SAL><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>7782</EMPNO><ENAME>CLAR
K</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981-06-09</HIREDATE><SAL>24
50</SAL><DEPTNO>10</DEPTNO></ROW><ROW><EMPNO>7839</EMPNO><ENAME>KING</ENAME><JOB
>PRESIDENT</JOB><HIREDATE>1981-11-17</HIREDATE><SAL>5000</SAL><DEPTNO>10</DEPTNO
></ROW><ROW><EMPNO>7844</EMPNO><ENAME>TURNER</ENAME><JOB>SALESMAN</JOB><MGR>7698
</MGR><HIREDATE>1981-09-08</HIREDATE><SAL>1500</SAL><COMM>0</COMM><DEPTNO>30</DE
PTNO></ROW><ROW><EMPNO>7900</EMPNO><ENAME>JAMES</ENAME><JOB>CLERK</JOB><MGR>7698
</MGR><HIREDATE>1981-12-03</HIREDATE><SAL>950</SAL><DEPTNO>30</DEPTNO></ROW><ROW
><EMPNO>7902</EMPNO><ENAME>FORD</ENAME><JOB>ANALYST</JOB><MGR>7566</MGR><HIREDAT
E>1981-12-03</HIREDATE><SAL>3000</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>7934<
/EMPNO><ENAME>MILLER</ENAME><JOB>CLERK</JOB><MGR>7782</MGR><HIREDATE>1982-01-23<
/HIREDATE><SAL>1300</SAL><DEPTNO>10</DEPTNO></ROW></ROWSET>


経過: 00:00:00.41
SCOTT>


ちなみに、もうお気づきだと思うが、上記のようにorder by句を付けたとしてもエラーにはならないが指定した列でソートされることはないのでご注意を!
ソートした結果が欲しい場合には副問い合せを利用するとよいだろう。


SCOTT> select
2 sys_xmlagg(
3 xmlelement("ROW",
4 xmlforest(
5 empno,
6 ename,
7 job,
8 mgr,
9 hiredate,
10 sal,
11 comm,
12 deptno
13 ))) xmldoc
14 from
15 (select * from emp order by empno) alias_of_emp
16 /

XMLDOC
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<ROWSET>
<ROW><EMPNO>7369</EMPNO><ENAME>SMITH</ENAME><JOB>CLERK</JOB><MGR>7902</MGR><HIRE
DATE>1980-12-17</HIREDATE><SAL>800</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>749
9</EMPNO><ENAME>ALLEN</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-02
-20</HIREDATE><SAL>1600</SAL><COMM>300</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPN
O>7521</EMPNO><ENAME>WARD</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>198
1-02-22</HIREDATE><SAL>1250</SAL><COMM>500</COMM><DEPTNO>30</DEPTNO></ROW><ROW><
EMPNO>7566</EMPNO><ENAME>JONES</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE
>1981-04-02</HIREDATE><SAL>2975</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>7654</
EMPNO><ENAME>MARTIN</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-09-2
8</HIREDATE><SAL>1250</SAL><COMM>1400</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO
>7698</EMPNO><ENAME>BLAKE</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981
-05-01</HIREDATE><SAL>2850</SAL><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>7782</EMPNO
><ENAME>CLARK</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981-06-09</HIRE
DATE><SAL>2450</SAL><DEPTNO>10</DEPTNO></ROW><ROW><EMPNO>7839</EMPNO><ENAME>KING
</ENAME><JOB>PRESIDENT</JOB><HIREDATE>1981-11-17</HIREDATE><SAL>5000</SAL><DEPTN
O>10</DEPTNO></ROW><ROW><EMPNO>7844</EMPNO><ENAME>TURNER</ENAME><JOB>SALESMAN</J
OB><MGR>7698</MGR><HIREDATE>1981-09-08</HIREDATE><SAL>1500</SAL><COMM>0</COMM><D
EPTNO>30</DEPTNO></ROW><ROW><EMPNO>7900</EMPNO><ENAME>JAMES</ENAME><JOB>CLERK</J
OB><MGR>7698</MGR><HIREDATE>1981-12-03</HIREDATE><SAL>950</SAL><DEPTNO>30</DEPTN
O></ROW><ROW><EMPNO>7902</EMPNO><ENAME>FORD</ENAME><JOB>ANALYST</JOB><MGR>7566</
MGR><HIREDATE>1981-12-03</HIREDATE><SAL>3000</SAL><DEPTNO>20</DEPTNO></ROW><ROW>
<EMPNO>7934</EMPNO><ENAME>MILLER</ENAME><JOB>CLERK</JOB><MGR>7782</MGR><HIREDATE
>1982-01-23</HIREDATE><SAL>1300</SAL><DEPTNO>10</DEPTNO></ROW><ROW><EMPNO>9999</
EMPNO><ENAME>ほげ</ENAME><JOB>ENGINEER</JOB><MGR>7566</MGR><HIREDATE>2008-01-01<
/HIREDATE><SAL>2500</SAL><DEPTNO>20</DEPTNO></ROW></ROWSET>


経過: 00:00:00.41


さらに前回までに紹介した、DBMS_XMLGEN.GETXMLやDBMS_XMLGEN.GETXMLTYPE()では関数に渡すクエリーにorder by句を付加すればソートできる。

SCOTT> select
2 dbms_xmlgen.getxml(sqlQuery=>'select * from emp order by empno') xmldoc
3 from dual
4 /

XMLDOC
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>80-12-17</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-02-20</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-02-22</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-04-02</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-09-28</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-05-01</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-06-09</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>81-11-17</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-09-08</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>81-12-03</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>81-12-03</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>82-01-23</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>08-01-01</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
</ROWSET>



経過: 00:00:00.65
SCOTT>


これは書く必要は無かったかもしれないが念のため。
XMLQuery()関数や、XMLTable()関数ではXQueryのFLWOR式でorder by句を使えばソートできる。

SCOTT> select
2 xmlroot(xmldoc.column_value, version '1.0')
3 from
4 xmltable(
5 '<ROWSET>{
6 for $d in ora:view("EMP")
7 order by $d
8 return $d
9 }</ROWSET>'
10 ) xmldoc
11 /

XMLROOT(XMLDOC.COLUMN_VALUE,VERSION'1.0')
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>1980-12-17</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-02-20</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-02-22</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-04-02</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-09-28</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-05-01</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-06-09</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>1981-11-17</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-09-08</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-12-03</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>1981-12-03</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>1982-01-23</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>2008-01-01</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
</ROWSET>


経過: 00:00:00.30
SCOTT>

次回へつづく。

| | コメント (0) | トラックバック (0)

2008年2月13日 (水)

Oracle de XMLDB #21 - Relational dataをXMLへ #4

さて、リレーショナルデータをXMLへ変換する方法の4つ目は、以前から提供されているPL/SQLのDBMS_XMLGENパッケージのgetXML()関数を利用する例です。
前回利用したgetXMLType()関数がXMLTypeインスタンスを返してくるのに対して、こちらはCLOB型のインスタンスを返してきます。しかも一時LOBが生成されます。(一時LOBを作成しない関数もあります)




バックナンバー:

Oracle de XMLDB #18 - Relational dataをXMLへ #1
Oracle de XMLDB #19 - Relational dataをXMLへ #2
Oracle de XMLDB #20 - Relational dataをXMLへ #3


おお〜っ、XMLTypeインスタンスを返す他のどれよりも遅いですね。今回利用した関数は内部で一時LOBを作る為に負荷が高いのですかね??(あくまで個人的な推測です。)

SCOTT> select
2 dbms_xmlgen.getXML(sqlQuery=>'select * from emp') as xmldoc
3 from dual
4 /

XMLDOC
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>08-01-01</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>80-12-17</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-02-20</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-02-22</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-04-02</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-09-28</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-05-01</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-06-09</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>81-11-17</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-09-08</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>81-12-03</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>81-12-03</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>82-01-23</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
</ROWSET>



経過: 00:00:00.65
SCOTT>

今回まででOracle11gデータベース側だけでリレーショナルデータをXMLへ変換する方法の簡単な実験は終わりです。
次回はクライアント側でリレーショナルデータを取り出してからXMLへ変換する方法でも試してみますか・・・・

| | コメント (0) | トラックバック (0)

2008年2月12日 (火)

Oracle de XMLDB #20 - Relational dataをXMLへ #3

さて前回に引き続きリレーショナルデータをXMLへ変換する方法の3つ目は、以前から提供されているPL/SQLのDBMS_XMLGENパッケージのgetXMLType()関数を利用する例です。


バックナンバー:
Oracle de XMLDB #18 - Relational dataをXMLへ #1
Oracle de XMLDB #19 - Relational dataをXMLへ #2

では早速取りかかる。

SCOTT> select
2 dbms_xmlgen.getXMLType(sqlQuery=>'select * from emp') as column_value
3 from dual
4 /

COLUMN_VALUE
--------------------------------------------------------------------------------
<ROWSET>
<ROW>
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>08-01-01</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>80-12-17</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-02-20</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-02-22</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-04-02</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-09-28</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-05-01</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-06-09</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>81-11-17</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-09-08</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>81-12-03</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>81-12-03</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>82-01-23</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
</ROWSET>


経過: 00:00:00.46

おや〜、SQL/XMLXMLQUERY関数XMLTABLE関数だけを利用した結果とは決定的な違いが1つあるのにお気づきだろうか?

そう、この時点で既にインデントされ改行が付加され人が読み易い形式に整形されている。Oracleさんの気まぐれなのか・・・・・・

DBMS_XMLGEN.getXMLType()を利用した場合もXMLQUERY関数XMLTABLE関数だけを利用した場合同様XML宣言は無い。

いつものXMLROOT()関数でXML宣言を付加してみる。

SCOTT> select
2 xmlroot(
3 dbms_xmlgen.getXMLType(sqlQuery=>'select * from emp')
4 ,version '1.0'
5 ) as column_value
6 from dual
7 /

COLUMN_VALUE
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>08-01-01</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>80-12-17</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-02-20</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-02-22</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-04-02</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-09-28</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-05-01</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>81-06-09</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>81-11-17</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>81-09-08</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>81-12-03</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>81-12-03</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>82-01-23</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
</ROWSET>


経過: 00:00:00.58
SCOTT>

PL/SQLパッケージを利用している影響なのだろう。SQL/XML関数だけの場合よりは負荷はおおきいようだ。

ではまた。

| | コメント (0) | トラックバック (0)

2008年2月11日 (月)

Oracle de XMLDB #19 - Relational dataをXMLへ #2

Relational dataからXMLを生成する方法の2つ目は、SQL/XMLXMLQUERY()とOracleが提供しているXQuery関数であるora:view()を組み合わせる方法。


バックナンバー: Oracle de XMLDB #18 - Relational dataからXMLへ #1

では、早速試してみる。

SCOTT> select * from emp
2 /

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
9999 ほげ ENGINEER 7566 08-01-01 2500 20
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500 30
7566 JONES MANAGER 7839 81-04-02 2975 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850 30
7782 CLARK MANAGER 7839 81-06-09 2450 10
7839 KING PRESIDENT 81-11-17 5000 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7900 JAMES CLERK 7698 81-12-03 950 30
7902 FORD ANALYST 7566 81-12-03 3000 20
7934 MILLER CLERK 7782 82-01-23 1300 10

13行が選択されました。

経過: 00:00:00.00
SCOTT>
SCOTT> select
2 xmlquery(
3 '<ROWSET>{
4 for $d in ora:view("EMP")
5 return $d
6 }</ROWSET>'
7 returning content
8 ) as COLUMN_VALUE
9 from dual
10 /

COLUMN_VALUE
--------------------------------------------------------------------------------
<ROWSET><ROW><EMPNO>9999</EMPNO><ENAME>ほげ</ENAME><JOB>ENGINEER</JOB><MGR>7566<
/MGR><HIREDATE>2008-01-01</HIREDATE><SAL>2500</SAL><DEPTNO>20</DEPTNO></ROW><ROW
><EMPNO>7369</EMPNO><ENAME>SMITH</ENAME><JOB>CLERK</JOB><MGR>7902</MGR><HIREDATE
>1980-12-17</HIREDATE><SAL>800</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>7499</E
MPNO><ENAME>ALLEN</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-02-20<
/HIREDATE><SAL>1600</SAL><COMM>300</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>75
21</EMPNO><ENAME>WARD</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-02
-22</HIREDATE><SAL>1250</SAL><COMM>500</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPN
O>7566</EMPNO><ENAME>JONES</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>198
1-04-02</HIREDATE><SAL>2975</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>7654</EMPN
O><ENAME>MARTIN</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-09-28</H
IREDATE><SAL>1250</SAL><COMM>1400</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>769
8</EMPNO><ENAME>BLAKE</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981-05-
01</HIREDATE><SAL>2850</SAL><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>7782</EMPNO><EN
AME>CLARK</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981-06-09</HIREDATE
><SAL>2450</SAL><DEPTNO>10</DEPTNO></ROW><ROW><EMPNO>7839</EMPNO><ENAME>KING</EN
AME><JOB>PRESIDENT</JOB><HIREDATE>1981-11-17</HIREDATE><SAL>5000</SAL><DEPTNO>10
</DEPTNO></ROW><ROW><EMPNO>7844</EMPNO><ENAME>TURNER</ENAME><JOB>SALESMAN</JOB><
MGR>7698</MGR><HIREDATE>1981-09-08</HIREDATE><SAL>1500</SAL><COMM>0</COMM><DEPTN
O>30</DEPTNO></ROW><ROW><EMPNO>7900</EMPNO><ENAME>JAMES</ENAME><JOB>CLERK</JOB><
MGR>7698</MGR><HIREDATE>1981-12-03</HIREDATE><SAL>950</SAL><DEPTNO>30</DEPTNO></
ROW><ROW><EMPNO>7902</EMPNO><ENAME>FORD</ENAME><JOB>ANALYST</JOB><MGR>7566</MGR>
<HIREDATE>1981-12-03</HIREDATE><SAL>3000</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMP
NO>7934</EMPNO><ENAME>MILLER</ENAME><JOB>CLERK</JOB><MGR>7782</MGR><HIREDATE>198
2-01-23</HIREDATE><SAL>1300</SAL><DEPTNO>10</DEPTNO></ROW></ROWSET>
経過: 00:00:00.10
SCOTT>

XMLTABLE()関数を使った場合と変るところはないが、関数本来の使い道からすればXMLQUERY()関数を使う方が自然に感じる。(まあ、どちらを使っても可能であることはまちがいないのですが。。)


最後に、前回も行ったようにXMLROOT()関数を利用しXML宣言を追加したXMLTypeインスタンスを取得してみた。

SCOTT> select
2 xmlroot(
3 xmlquery(
4 '<ROWSET>{
5 for $d in ora:view("EMP")
6 return $d
7 }</ROWSET>'
8 returning content
9 ),
10 version '1.0'
11 ) as column_value
12 from dual
13 /

COLUMN_VALUE
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>2008-01-01</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>1980-12-17</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-02-20</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-02-22</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-04-02</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-09-28</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-05-01</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-06-09</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>1981-11-17</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-09-08</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-12-03</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>1981-12-03</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>1982-01-23</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
</ROWSET>


経過: 00:00:00.58
SCOTT>

ではまた。

| | コメント (0) | トラックバック (0)

2008年2月10日 (日)

Oracle de XMLDB #18 - Relational dataをXMLへ #1

Oracle XML DBリポジトリ関連の話はしばらく脇に置いておき、これから数回に分けてリレーショナル表からXMLを生成する方法について、備忘録の意味も含めて書いておくことにする。

● 環境データ

Server : Dynabook SS SX/210LNLW (RAM:768MB) 
CentOS5
Oracle11g EE R1 11.1.0.6.0 for Linux x86

Client : Apple PowerMac G5 Dual 2.7Ghz (RAM:1GB)
MacOSX Tiger 10.4.11 Server
Oracle10g Instant Client 10g R1 for MacOSX(PPC)

表を問い合わせXMLTypeインスタンスを返す方法は複数ある。まず最初に紹介するのは、XMLTABLE()関数のXqueryでora:view()関数を使う方法。

XMLTABLE()関数は、SQL/XMLで提供される標準関数で、本来はXMLデータをリレーショナルフォーマットへマッピングする為に利用する関数なのだが、今回は本来の目的とは異なる使い方をしてみた。
XMLTABLE()関数でリレーショナル表からXMLTypeインスタンスを取得するには、OracleがXXQuery向に提供している ora:view()関数を利用する。(Oracleが独自に拡張したXQuery向け関数の名前空間は、ora:)
ora:view()関数は、XQueryの標準関数であるfn:doc()関数を利用する感覚で利用できる。


以下の例では、XMLTABLE()関数でCOLUMNS句を指定していしないのがポイント。尚、COLUMN_VALUE疑似列を利用しています。

Last login: Sat Feb  9 06:46:43 on console
Welcome to Darwin!
G5Server:˜ discus$ sqlplus /nolog

SQL*Plus: Release 10.1.0.3.0 - Production on 土 2月 9 15:30:44 2008

Copyright (c) 1982, 2004, Oracle. All rights reserved.

SCOTT> conn scott/tiger@lampeye
接続されました。
SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
PL/SQL Release 11.1.0.6.0 - Production
CORE 11.1.0.6.0 Production
TNS for Linux: Version 11.1.0.6.0 - Production
NLSRTL Version 11.1.0.6.0 - Production

SCOTT> set pagesize 1000
SCOTT> set long 4000
SCOTT> set sqlterm off
SCOTT> set linesize 80
SCOTT> l
1 select xmldoc.COLUMN_VALUE
2 from
3 xmltable(
4 '<ROWSET>{
5 for $d in ora:view("EMP")
6 return $d
7 }</ROWSET>'
8* ) xmldoc
SCOTT> /

COLUMN_VALUE
--------------------------------------------------------------------------------
<ROWSET><ROW><EMPNO>9999</EMPNO><ENAME>ほげ</ENAME><JOB>ENGINEER</JOB><MGR>7566<
/MGR><HIREDATE>2008-01-01</HIREDATE><SAL>2500</SAL><DEPTNO>20</DEPTNO></ROW><ROW
><EMPNO>7369</EMPNO><ENAME>SMITH</ENAME><JOB>CLERK</JOB><MGR>7902</MGR><HIREDATE
>1980-12-17</HIREDATE><SAL>800</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>7499</E
MPNO><ENAME>ALLEN</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-02-20<
/HIREDATE><SAL>1600</SAL><COMM>300</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>75
21</EMPNO><ENAME>WARD</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-02
-22</HIREDATE><SAL>1250</SAL><COMM>500</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPN
O>7566</EMPNO><ENAME>JONES</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>198
1-04-02</HIREDATE><SAL>2975</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMPNO>7654</EMPN
O><ENAME>MARTIN</ENAME><JOB>SALESMAN</JOB><MGR>7698</MGR><HIREDATE>1981-09-28</H
IREDATE><SAL>1250</SAL><COMM>1400</COMM><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>769
8</EMPNO><ENAME>BLAKE</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981-05-
01</HIREDATE><SAL>2850</SAL><DEPTNO>30</DEPTNO></ROW><ROW><EMPNO>7782</EMPNO><EN
AME>CLARK</ENAME><JOB>MANAGER</JOB><MGR>7839</MGR><HIREDATE>1981-06-09</HIREDATE
><SAL>2450</SAL><DEPTNO>10</DEPTNO></ROW><ROW><EMPNO>7839</EMPNO><ENAME>KING</EN
AME><JOB>PRESIDENT</JOB><HIREDATE>1981-11-17</HIREDATE><SAL>5000</SAL><DEPTNO>10
</DEPTNO></ROW><ROW><EMPNO>7844</EMPNO><ENAME>TURNER</ENAME><JOB>SALESMAN</JOB><
MGR>7698</MGR><HIREDATE>1981-09-08</HIREDATE><SAL>1500</SAL><COMM>0</COMM><DEPTN
O>30</DEPTNO></ROW><ROW><EMPNO>7900</EMPNO><ENAME>JAMES</ENAME><JOB>CLERK</JOB><
MGR>7698</MGR><HIREDATE>1981-12-03</HIREDATE><SAL>950</SAL><DEPTNO>30</DEPTNO></
ROW><ROW><EMPNO>7902</EMPNO><ENAME>FORD</ENAME><JOB>ANALYST</JOB><MGR>7566</MGR>
<HIREDATE>1981-12-03</HIREDATE><SAL>3000</SAL><DEPTNO>20</DEPTNO></ROW><ROW><EMP
NO>7934</EMPNO><ENAME>MILLER</ENAME><JOB>CLERK</JOB><MGR>7782</MGR><HIREDATE>198
2-01-23</HIREDATE><SAL>1300</SAL><DEPTNO>10</DEPTNO></ROW></ROWSET>


経過: 00:00:00.11
SCOTT>


これだとXML宣言が無い。ではどうやってXML宣言を付加するかと言えば、XMLRoot()関数を使う。
XMLRoot()関数は2005年まではSQL/XMLの標準関数だったが現在は標準関数ではない。但し、Oracleでは利用できるのでXMLRoot()関数を利用してXML宣言を付加することができる。

では早速試してみよう!。

SCOTT> select
2 xmlroot(xmldoc.column_value,version '1.0')
3 from
4 xmltable(
5 '<ROWSET>{
6 for $d in ora:view("EMP")
7 return $d
8 }</ROWSET>'
9 ) xmldoc
10 /

XMLROOT(XMLDOC.COLUMN_VALUE,VERSION'1.0')
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPNO>9999</EMPNO>
<ENAME>ほげ</ENAME>
<JOB>ENGINEER</JOB>
<MGR>7566</MGR>
<HIREDATE>2008-01-01</HIREDATE>
<SAL>2500</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>1980-12-17</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-02-20</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-02-22</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-04-02</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-09-28</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-05-01</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>1981-06-09</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>1981-11-17</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-09-08</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>1981-12-03</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>1981-12-03</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>1982-01-23</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
</ROWSET>

経過: 00:00:00.33
SCOTT>

あれ、XMLRoot()関数に渡しているXMLTABLE()関数で取得したXMLTypeインスタンスには改行がありませんでしたが、XMLROOT()関数を利用すると改行が付加されたXMLTypeインスタンスが返されます。また、その影響だと思うが経過時間も増えている。

こりゃ参った〜という感じです。以前もOracle XML DBに関するエントリでwhitespaceのpreserve/stripは現時点のOracle XML DBでは明示的に制御できないということは書いていましたが思わぬところでwhitespaceかってに付加されるという動きには戸惑いますね。(利用する側で制御できるようにしてもらったほうがスッキリするように感じます。)


トレースして詳細に追跡したわけでは無いのであくまで想像の域を脱していないのですが、もしかすると、XMLROOT()関数はXMLTypeインスタンスを受け取りXML宣言を付加して返してくる際、XML宣言を追加したDOMを生成した上でXMLTypeインスタンスを返してくるのではないかと考えています。(くどいようですが、これは私の推測に過ぎませんので誤解なさらないようにしてください。)

時間があればもっと深〜〜〜く追っかけてみたい現象なのでとりあえず、TODOリストに追加しておきますかね。

では次回へつづく。

| | コメント (0) | トラックバック (1)

2008年1月22日 (火)

24(テレビドラマではないよ)

Wigitize

24時間で作られたドットコムサイト『Wigitize』でも取り上げられていたのでいろいろ覗いてみたついでにWidgetを作って貼付けてみた。元からあるココログの「最近の記事」と比べても見劣りしないでしょ。
記事にもあるように24時間でどのようにしてWigitizeを構築していったのか、プロセスが細かく書かれていて実に面白い。


ココログオリジナルの「最新の記事」(左)とWigitizeで作って少々加工した「最新の記事」(右)
9 8

あ、24時間で作るといえば、Wif2008の予選会も24時間で与えられたテーマのWebデザインを完成させるのが条件でしたね。予選の作品が公開されたようです。。。Wif2008ネタは別エントリで。

日本からは8チームエントリしているように見えるが実際には5チームとのこと。
Wif2008_preselect

| | コメント (0) | トラックバック (0)

2008年1月 2日 (水)

Oracle de XMLDB #17

「XMLマスター:プロフェッショナル(データベース) 試験」のサンプル問題がXML技術者育成推進委員会のサイトに掲載されている。
この問題の幾つかは直接XML DBを操作して確認することができる問題なのだが、それらの問題をOracle11g R1 11.1.0.6.0を利用して試す場合には次の2点には注意しておいたほうがよいだろう。

● 最初はSQL*Plusの仕様による影響。

SQL*PlusのXQueryコマンドで試す場合以下のように@がSQL*PlusのSTARTコマンとして実行されてしまう。
SCOTT> xquery
2 for $n in fn:doc("/public/scott/xml/example2.xml")/list
3 return
4 <codeList>
5 <code> {
6 @code
SP2-0310: ファイル"code.sql"をオープンできません。
6 .
SCOTT>

これを回避する方法は以前も紹介した方法でSQL*PlusのSTARTコマンドして実行されることを回避できる。

SCOTT> xquery
2 for $n in fn:doc("/public/scott/xml/example2.xml")/list
3 return
4 <codeList>
5 <code>{
6 (::) @code
7 }</code>
・・・以下省略・・・

「XMLマスター:プロフェッショナル(データベース) 試験のサンプル問題」の問題2をOracle11g R1 11.1.0.6.0で試す場合には忘れずに!


● もう一つはテキストノードのwhitespaceの取扱いに関するもの。

Oracle11g R1 11.1.0.6.0のXMLDBではテキストノードに対するwhitespaceの取扱いは常にstripであること。以下の例を見ていただければ一目瞭然。
ということで「XMLマスター:プロフェッショナル(データベース) 試験のサンプル問題」の問題3をOracle11g R1 11.1.0.6.0で実行した場合<space> </space>というノードの空白は削除されてしまうのでこれまたOracle11g R1ではそのような実装になっているということをお忘れなく。

SCOTT> !cat sample.xml
<?xml version="1.0" encoding="utf-8"?>
<space> </space>

SCOTT> declare
2 r boolean;
3 begin
4 r := dbms_xdb.createresource(
5 '/public/scott/xml/sample.xml',
6 bfilename('SCOTT_XMLDIR','sample.xml'),
7 nls_charset_id('AL32UTF8'));
8 commit;
9 end;
10 /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> xquery
2 fn:doc("/public/scott/xml/sample.xml")/space
3 /

Result Sequence
--------------------------------------------------------------------------------
<space/>

SCOTT>


ちなみにオープンソースのSaxon Bではテキストノードのwhitespaceの扱いは指定可能なのでXMLマスタープロフェッショナル(データベース)のようなベンダー比依存の試験勉強の為だけであればSaxon Bを使ったほうが無難かもしれない。ただ、プロジェクトでOracle11g R1のXML DBを利用するのであればOracle11g R1を利用して検証したほうがいいのは言うまでもない。

以下、saxon 9.0.0J(saxon B 9.0.0.2のjava版)を利用して上記2点に関連する部分を実行した例

環境:MacOSX Server 10.4.11 Tiger

● SAXON B 9.0.0.2(java版)をダウンロード、unzipする。

今回は/User/Sharedで作業を行うことにした。Webブラウザでダウンロードしてもいいのだが折角なので全部コマンドで行っちゃいましょう。
curlコマンドSAXON B 9.0.0.2(Java版)をダウンロード後、unzip。

G5Server:˜ oracle$ java -version
java version "1.5.0_13"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_13-b05-241)
Java HotSpot(TM) Client VM (build 1.5.0_13-121, mixed mode)
G5Server:˜ oracle$
G5Server:˜ oracle$ cd /Users/Shared/
G5Server:/Users/Shared oracle$
G5Server:/Users/Shared oracle$ curl -L -o saxonb9-0-0-2j.zip http://prdownloads.sourceforge.net/saxon/saxonb9-0-0-2j.zip
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1862k 100 1862k 0 0 144k 0 0:00:12 0:00:12 --:--:-- 144k

G5Server:/Users/Shared oracle$ unzip saxonb9-0-0-2j.zip -d saxonb9-0-0-2j
Archive: saxonb9-0-0-2j.zip
inflating: saxonb9-0-0-2j/saxon9-ant.jar
inflating: saxonb9-0-0-2j/saxon9-dom.jar
inflating: saxonb9-0-0-2j/saxon9-dom4j.jar
inflating: saxonb9-0-0-2j/saxon9-jdom.jar
inflating: saxonb9-0-0-2j/saxon9-s9api.jar
inflating: saxonb9-0-0-2j/saxon9-sql.jar
inflating: saxonb9-0-0-2j/saxon9-xom.jar
inflating: saxonb9-0-0-2j/saxon9-xpath.jar
inflating: saxonb9-0-0-2j/saxon9-xqj.jar
inflating: saxonb9-0-0-2j/saxon9.jar
G5Server:/Users/Shared oracle$ cd saxonb9-0-0-2j


● XMLファイルとXQueryファイルを用意する。

前述したXMLマスタープロフェッショナル(データベース)試験のサンプル問題元にXMLファイルとXQueryファイルを準備しておく。
SAXON Bのコマンドラインでは直接XQueryを記述できずXQueryを記述したファイルを指定する必要がある為。)

G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ ll
total 10584
-rw-r--r-- 1 oracle wheel 444 Dec 31 17:38 example.xml
-rw-r--r-- 1 oracle wheel 40 Dec 31 17:38 query1.xql
-rw-r--r-- 1 oracle wheel 58 Dec 31 17:38 query2.xql
-rw-r--r-- 1 oracle wheel 199 Dec 31 17:38 query_a.xql
-rw-r--r-- 1 oracle wheel 188 Dec 31 17:38 query_b.xql
-rw-r--r-- 1 oracle wheel 204 Dec 31 17:38 query_c.xql
-rw-r--r-- 1 oracle wheel 189 Dec 31 17:38 query_d.xql
-rw-r--r-- 1 oracle wheel 57 Dec 31 17:38 result.xml
-rw-r--r-- 1 oracle wheel 108 Dec 31 17:38 sample.xml
-rw-r--r-- 1 oracle wheel 56 Dec 31 17:38 sample2.xml
-rw-r--r-- 1 oracle wheel 23963 Nov 30 14:35 saxon9-ant.jar
-rw-r--r-- 1 oracle wheel 110602 Nov 30 14:35 saxon9-dom.jar
-rw-r--r-- 1 oracle wheel 30000 Nov 30 14:35 saxon9-dom4j.jar
-rw-r--r-- 1 oracle wheel 32743 Nov 30 14:35 saxon9-jdom.jar
-rw-r--r-- 1 oracle wheel 110818 Nov 30 14:35 saxon9-s9api.jar
-rw-r--r-- 1 oracle wheel 45598 Nov 30 14:35 saxon9-sql.jar
-rw-r--r-- 1 oracle wheel 45218 Nov 30 14:35 saxon9-xom.jar
-rw-r--r-- 1 oracle wheel 43536 Nov 30 14:35 saxon9-xpath.jar
-rw-r--r-- 1 oracle wheel 173255 Nov 30 14:35 saxon9-xqj.jar
-rw-r--r-- 1 oracle wheel 4737705 Nov 30 14:35 saxon9.jar
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$


● SAXON BのXQueryのコマンド形式は以下のようにして確認できます。

G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query -?
Saxon 9.0.0.2J from Saxonica
Usage: java net.sf.saxon.Query [options] query {param=value}...
Options:
-cr:classname Use specified CollectionURIResolver class
-dtd:on|off Validate using DTD
-expand:on|off Expand defaults defined in schema/DTD
-explain[:filename] Display compiled expression tree
-ext:[on|off] Allow|Disallow external Java functions
-l:on|off Line numbering for source document
-mr:classname Use specified ModuleURIResolver class
-o:filename Send output to named file
-outval:recover|fatal Handling of validation errors on result document
-p Recognize Saxon file extensions and query parameters
-pipe:push|pull Execute internally in push or pull mode
-projection:[on|off] Use|Don't use source document projection
-r:classname Use URIResolver class
-repeat:N Repeat N times for performance measurement
-s:file|URI Provide initial context document
-sa Schema-aware query (requires Saxon-SA)
-strip:all|none|ignorable Strip whitespace text nodes
-t Display version and timing information
-tree:tiny|linked Select tree model
-T[:classname] Use TraceListener class
-TJ Trace calls to external Java functions
-u Names are URLs not filenames
-val:strict|lax Validate using schema
-wrap:on|off Wrap result sequence in XML elements
-x:classname Parser (XMLReader) used for source files
-xi:on|off Expand XInclude on all documents
-xmlversion:1.0|1.1 Version of XML to be handled
-? Display this message
param=value Set query string parameter
+param=value Set query document parameter
!option=value Set serialization option
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$

SAXON B「XMLマスター:プロフェッショナル(データベース) 試験のサンプル問題」の問題2を試す。

G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ cat example.xml
<?xml version="1.0" encoding="utf-8"?>
<logList>
<list code="w001" message="警告1"/>
<list code="w002" message="警告2"/>
<list code="e001" message="エラー1"/>
<list code="e002" message="エラー2"/>
<day date="2007-12-01">
<log time="10:00:00" code="w001"/>
<log time="14:00:00" code="e001"/>
</day>
<day date="2007-12-02">
<log time="13:00:00" code="e002"/>
<log time="15:00:00" code="e001"/>
</day>
</logList>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ cat -n query_a.xql
1 <result>{
2 let $doc := fn:doc("example.xml")
3 for $log in $doc//log
4 return
5 <log>{
6 $log/../@date,
7 $log/@time,
8 $doc//list[@code eq $log/@code]/@message
9 }</log>
10 }</result>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query query_a.xql
<?xml version="1.0" encoding="UTF-8"?>
<result>
<log date="2007-12-01" time="10:00:00" message="警告1"/>
<log date="2007-12-01" time="14:00:00" message="エラー1"/>
<log date="2007-12-02" time="13:00:00" message="エラー2"/>
<log date="2007-12-02" time="15:00:00" message="エラー1"/>
</result>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ cat -n query_b.xql
1 <result>{
2 let $doc := fn:doc("example.xml")
3 for $log in $doc//log
4 return
5 <log>{
6 ../@date,
7 @time,
8 ../../list[@code = $log/@code]/@message
9 }</log>
10 }</result>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query query_b.xql
Error on line 6 of file:/Users/Shared/saxonb9-0-0-2j/query_b.xql:
XPDY0002: The context item is not set
Query processing failed: Run-time errors were reported
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ cat -n query_c.xql
1 <result>{
2 let $doc := fn:doc("example.xml")
3 for $day in $doc//day
4 return
5 <log>{
6 $day/@date,
7 $day/log/@time,
8 $doc//list[@code eq $day/log/@code]/@message
9 }</log>
10 }</result>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query query_c.xql
Error on line 7 of file:/Users/Shared/saxonb9-0-0-2j/query_c.xql:
XQDY0025: Cannot create an element having two attributes with the same name: @time
Query processing failed: Run-time errors were reported
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ cat -n query_d.xql
1 <result>{
2 let $doc := fn:doc("example.xml")
3 for $day in $doc//day
4 return
5 <log>{
6 @date,
7 log/@time,
8 ../list[@code = $day/log/@code]/@message
9 }</log>
10 }</result>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query query_d.xql
Error on line 6 of file:/Users/Shared/saxonb9-0-0-2j/query_d.xql:
XPDY0002: The context item for axis step attribute::attribute(date, xs:anyAtomicType) is undefined
Query processing failed: Run-time errors were reported


SAXON Bではテキストノードのwhitespaceの取扱いを-stripオプションで指示できる。

G5Server:/Users/shared/saxonb9-0-0-2j oracle$ cat -n sample2.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <space> </space>
G5Server:/Users/shared/saxonb9-0-0-2j oracle$ cat -n query2.xql
1 fn:doc("sample2.xml")/space
G5Server:/Users/shared/saxonb9-0-0-2j oracle$
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query query2.xql
<?xml version="1.0" encoding="UTF-8"?>
<space> </space>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query -strip:all query2.xql
<?xml version="1.0" encoding="UTF-8"?>
<space/>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query -strip:none query2.xql
<?xml version="1.0" encoding="UTF-8"?>
<space> </space>
G5Server:/Users/Shared/saxonb9-0-0-2j oracle$ java -cp saxon9.jar net.sf.saxon.Query -strip:ignorable query2.xql
<?xml version="1.0" encoding="UTF-8"?>
<space> </space>




● バックナンバー
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4
Oracle de XMLDB #5 - Oracle11g環境再構築完了
Oracle de XMLDB #6 - Linux x86版再び。
Oracle de XMLDB #7 - 何かが違う!?
Oracle de XMLDB #8 - またまた少々脱線
Oracle de XMLDB #9 - またまた少々脱線の続き
Oracle de XMLDB #10 - 三度脱線
Oracle de XMLDB #11 - 三度脱線のおまけ
Oracle de XMLDB #12
Oracle de XMLDB #13
Oracle de XMLDB #14
Oracle de XMLDB #15
Oracle de XMLDB #16

| | コメント (0) | トラックバック (0)

2007年12月17日 (月)

Oracle de XMLDB #16

Oracle de XMLDB #13でも書いたxquery宣言のencodingがサポートされていないということも含めてOracle11g R1の以下マニュアルに記載されているので要確認。(備忘録)

Oracle® XML DB Developer's Guide 11g Release 1 (11.1) - Oracle XML DB Support for XQuery

前述のマニュアルにも記載されているが、boundary-spaceは未サポートとか。とりあえず試してみる。

Last login: Sun Dec 16 14:15:06 on console
Welcome to Darwin!
G5Server:˜ discus$ su - oracle
Password:
G5Server:˜ oracle$ ssh oracle@corydoras
oracle@corydoras's password:
Last login: Sat Dec 15 19:59:13 2007 from 192.168.1.19
[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 日 12月 16 18:03:04 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

> conn scott/tiger
接続されました。
SCOTT> set sqlterm off
SCOTT> set long 4000
SCOTT> set pagesize 1000
SCOTT> xquery
2 declare boundary-space preserve;
3 <result>
4 {
5 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
6 return
7 <greeting> { fn:concat("Hello, ", $i/text())
8 } </greeting>
9* } </result>
10 /
ERROR:
ORA-19107: 無効なXQueryX - 構成がサポートされていません - boundary-space preserve declaration

SCOTT> edit
file afiedt.bufが書き込まれました。

1 xquery
2 declare boundary-space strip;
3 <result>
4 {
5 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
6 return
7 <greeting> { fn:concat("Hello, ", $i/text())
8 } </greeting>
9* } </result>
SCOTT> /

Result Sequence
--------------------------------------------------------------------------------
<result><greeting>Hello, 03-1234-5555</greeting><greeting>Hello, 090-4321-7878</
greeting><greeting>Hello, 070-7777-8798</greeting><greeting>Hello, 06-1234-5555<
/greeting><greeting>Hello, 06-6860-0001</greeting><greeting>Hello, 090-6666-7878
</greeting><greeting>Hello, 080-9999-8798</greeting><greeting>Hello, 06-6860-000
1</greeting><greeting>Hello, 090-0066-0108</greeting><greeting>Hello, 090-3020-2
897</greeting></result>


SCOTT>

Oracle11g R1 11.6.0.1.0のXQueryでは、boundary-space preserveが未サポートということでboundary-space stripで処理しているということなんだね。




● バックナンバー
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4
Oracle de XMLDB #5 - Oracle11g環境再構築完了
Oracle de XMLDB #6 - Linux x86版再び。
Oracle de XMLDB #7 - 何かが違う!?
Oracle de XMLDB #8 - またまた少々脱線
Oracle de XMLDB #9 - またまた少々脱線の続き
Oracle de XMLDB #10 - 三度脱線
Oracle de XMLDB #11 - 三度脱線のおまけ
Oracle de XMLDB #12
Oracle de XMLDB #13
Oracle de XMLDB #14
Oracle de XMLDB #15

| | コメント (0) | トラックバック (0)

2007年12月16日 (日)

Oracle de XMLDB #15

さて、まだ脱線は続きます。(いつ戻るんだ〜〜!)

Oracle de XMLDB #13でXqueryのencodingが指定できないと書いたが、どうしても文字コードを変えたい場合はどうするんだろうか?

思い出したのがOracle de XMLDB #7 - 何かが違うでも書いたクライアント側のNLS_LANG環境変数で制御する方法。




● バックナンバー
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4
Oracle de XMLDB #5 - Oracle11g環境再構築完了
Oracle de XMLDB #6 - Linux x86版再び。
Oracle de XMLDB #7 - 何かが違う!?
Oracle de XMLDB #8 - またまた少々脱線
Oracle de XMLDB #9 - またまた少々脱線の続き
Oracle de XMLDB #10 - 三度脱線
Oracle de XMLDB #11 - 三度脱線のおまけ
Oracle de XMLDB #12
Oracle de XMLDB #13
Oracle de XMLDB #14


●このテスト環境の文字エンコーディングの概略図
NLS_LANG環境変数を変換したい文字コードへ変更すればうまく変換できるはず・・・・


Diagram_encoding

● まずは全てUTF-8で統一させている場合の例から。

MacOSXのterminalの文字エンコーディングもUTF-8にすることをお忘れなく。
Utf8


> conn scott/tiger
接続されました。
SCOTT> !echo $NLS_LANG
japanese_japan.AL32UTF8

SCOTT> set sqlterm off
SCOTT> set pagesize 1000
SCOTT> set long 4000
SCOTT>
SCOTT> select
2 xmlquery(
3 'xquery version "1.0";
4 <result>
5 {
6 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
7 return $i
8 }
9 </result>'
10 returning content
11 )
12 from
13* dual
SCOTT> /

XMLQUERY('XQUERYVERSION"1.0";<RESULT>{FOR$IINFN:DOC("/PUBLIC/SCOTT/XML/ADDRESSLI
--------------------------------------------------------------------------------
<result><電話番号 区分="自宅">03-1234-5555</電話番号>
<電話番号 区分="携帯">090-4321-7878</電話番号>
<電話番号 区分="携帯">070-7777-8798</電話番号>
<電話番号 区分="自宅">06-1234-5555</電話番号>
<電話番号 区分="会社">06-6860-0001</電話番号>
<電話番号 区分="携帯">090-6666-7878</電話番号>
<電話番号 区分="携帯">080-9999-8798</電話番号>
<電話番号 区分="会社">06-6860-0001</電話番号>
<電話番号 区分="携帯">090-0066-0108</電話番号>
<電話番号 区分="携帯">090-3020-2897</電話番号>
</result>

SCOTT> exit


● クライアント側のNLS_LANG=japanese_japan.JA16SJISTILDE、MacOSXのTerminalの文字エンコーディングもShift_JISへ変更して実行する。

Sjis

[oracle@corydoras ˜]$ export NLS_LANG=japanese_japan.JA16SJISTILDE
[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 金 12月 14 23:10:29 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

> conn scott/tiger
接続されました。

SCOTT> !echo $NLS_LANG
japanese_japan.JA16SJISTILDE

SCOTT> set sqlterm off
SCOTT> set pagesize 1000
SCOTT> set long 4000
SCOTT>
SCOTT> select
2 xmlquery(
3 'xquery version "1.0";
4 <result>
5 {
6 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
7 return $i
8 }
9 </result>'
10 returning content
11 )
12 from
13* dual
SCOTT> /

XMLQUERY('XQUERYVERSION"1.0";<RESULT>{FOR$IINFN:DOC("/PUBLIC/SCOTT/XML/ADDRESSLI
--------------------------------------------------------------------------------
<result><電話番号 区分="自宅">03-1234-5555</電話番号>
<電話番号 区分="携帯">090-4321-7878</電話番号>
<電話番号 区分="携帯">070-7777-8798</電話番号>
<電話番号 区分="自宅">06-1234-5555</電話番号>
<電話番号 区分="会社">06-6860-0001</電話番号>
<電話番号 区分="携帯">090-6666-7878</電話番号>
<電話番号 区分="携帯">080-9999-8798</電話番号>
<電話番号 区分="会社">06-6860-0001</電話番号>
<電話番号 区分="携帯">090-0066-0108</電話番号>
<電話番号 区分="携帯">090-3020-2897</電話番号>
</result>


これではなんとなく分かりずらいですね。ということで結果をHTMLへスプールして確認してみましょう。

SCOTT> set markup html on spool on
SCOTT> set echo off
<br>
SCOTT> spool result.html
<br>
SCOTT> /
<br>

・・・・・中略・・・・・

SCOTT> spo off
<br>
SCOTT> set markup html off
<br>
SCOTT> set echo on
SCOTT> !cat result.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=SHIFT_JIS">
<meta name="generator" content="SQL*Plus 11.1.0">
<style type="text/css">
body {font:10pt Arial,Helvetica,sans-serif;
color:black; background:White;}
p {font:10pt Arial,Helvetica,sans-serif;
color:black; background:White;}
table,tr,td {font:10pt Arial,Helvetica,sans-serif;
color:Black; background:#f7f7e7;
padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;}
th {font:bold 10pt Arial,Helvetica,sans-serif;
color:#336699; background:#cccc99; padding:0px 0px 0px 0px;}
h1 {font:16pt Arial,Helvetica,Geneva,sans-serif;
color:#336699; background-color:White;
border-bottom:1px solid #cccc99;
margin-top:0pt; margin-bottom:0pt;
padding:0px 0px 0px 0px;}
h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif;
color:#336699; background-color:White;
margin-top:4pt; margin-bottom:0pt;}
a {font:9pt Arial,Helvetica,sans-serif;
color:#663300; background:#ffffff;
margin-top:0pt; margin-bottom:0pt; vertical-align:top;}
</style>
<title>
SQL*Plus レポート
</title>
</head>
<body>
SCOTT> /
<br>
<p>
<table border="1" width="90%" summary="Script output">
<tr>
<th scope="col">
XMLQUERY('XQUERYVERSION"1.0";<RESULT>{FOR$IINFN:DOC("/PUBLIC/SCOTT/XML/ADDRESSLI
</th>
</tr>
<tr>
<td>
<result><電話番号 区分="自宅">03-1234-5555</電話番号>
<電話番号 区分="携帯">090-
4321-7878</電話番号>
<電話番号 区分="携帯">070-7777-8798</電話番号>
<電話番号 区
分="自宅">06-1234-5555</電話番号>
<電話番号 区分="会社">06-6860-0001</電話番号>

<電話番号 区分="携帯">090-6666-7878</電話番号>
<電話番号 区分="携帯">080-9999-87
98</電話番号>
<電話番号 区分="会社">06-6860-0001</電話番号>
<電話番号 区分="携帯
">090-0066-0108</電話番号>
<電話番号 区分="携帯">090-3020-2897</電話番号>
</resu
lt>
</td>
</tr>
</table>
<p>

SCOTT> spo off
<br>
</body>
</html>

SCOTT>

SQL*PlusでHTMLとして結果をSPOOLするコマンドがありますが、その機能を利用して文字エンコーディングがShift_JISになっているか確認しています。(太字で赤色で強調してある部分)
うまくShift_JISへ変換できているようです。
NLS_LANG環境変数で制御するしかないのはかなりトリッキーではあるけれど・・・)

| | コメント (0) | トラックバック (0)

2007年12月14日 (金)

Oracle de XMLDB #14

またXMLマスタープロフェッショナル(DB)試験ネタからは少々脱線している・・・。と気付きつつも、気になるとやらずに居られない性分なので。


● バックナンバー
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4
Oracle de XMLDB #5 - Oracle11g環境再構築完了
Oracle de XMLDB #6 - Linux x86版再び。
Oracle de XMLDB #7 - 何かが違う!?
Oracle de XMLDB #8 - またまた少々脱線
Oracle de XMLDB #9 - またまた少々脱線の続き
Oracle de XMLDB #10 - 三度脱線
Oracle de XMLDB #11 - 三度脱線のおまけ
Oracle de XMLDB #12
Oracle de XMLDB #13

前々回にも書いたがSQL*Plusでは、";"を入力してしまうとそれまで入力したSQL文を実行してくれる。

ただ、SQL文や、XQueryコマンドの実行には問題ないのだが、SQL/XMLでは少々困った問題を引き起こすんです。

以下の例をご覧ください。

> conn scott/tiger
接続されました。
SCOTT>
SCOTT>
SCOTT> select
2 xmlquery(
3 'xquery version "1.0";
ERROR:
ORA-01756: 引用符付き文字列が正しく終了していません

そうなんです!。
xmlquery()関数内あっても ";"(セミコロン)を入力する必要があるのですが、入力した時点で実行しようとしてしまうんです。(><)

これには困りました!。

無理矢理な対処として、エラーになっても気にせず前述のように入力後、SQL*Plusのeditコマンドで編集する方法もありますが、今回はマニュアル Oracle® XML DB Developer's Guide 11g Release 1 (11.1) - Using Namespaces with XQueryにも書かれている方法でやってみましょう。

● ";"(セミコロン)の後にXQeuryのコメントを付加する方法

SCOTT> 
SCOTT> select
2 xmlquery(
3 'xquery version "1.0"; (::)
4 declare namespace mo = "http://192.168.1.20/my_namespace"; (::)
5 declare function mo:phoneNumber($phone)
6 {
7 $phone/text()
8 }; (::)
9 (: query body :)
10 <result>
11 {
12 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
13 return
14 <greeting>
15 { fn:concat("Hello, ", mo:phoneNumber($i)) }
16 </greeting>
17 }
18 </result>'
19 returning content
20 )
21 from
22 dual
23 .
SCOTT> /

XMLQUERY('XQUERYVERSION"1.0";(::)DECLARENAMESPACEMO="HTTP://192.168.1.20/MY_NAME
--------------------------------------------------------------------------------
<result><greeting>Hello, 03-1234-5555</greeting><greeting>Hello, 090-4321-7878</
greeting><greeting>Hello, 070-7777-8798</greeting><greeting>Hello, 06-1234-5555<
/greeting><greeting>Hello, 06-6860-0001</greeting><greeting>Hello, 090-6666-7878
</greeting><greeting>Hello, 080-9999-8798</greeting><greeting>Hello, 06-6860-000
1</greeting><greeting>Hello, 090-0066-0108</greeting><greeting>Hello, 090-3020-2
897</greeting></result>


SCOTT>


● 次は、";"(セミコロン)を無視させる方法。

SCOTT> set sqlterm off
SCOTT> select
2 xmlquery(
3 'xquery version "1.0";
4 declare namespace mo = "http://192.168.1.20/my_namespace";
5 declare function mo:phoneNumber($phone)
6 {
7 $phone/text()
8 };
9 (: query body :)
10 <result>
11 {
12 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
13 return
14 <greeting>
15 { fn:concat("Hello, ", mo:phoneNumber($i)) }
16 </greeting>
17 }
18 </result>'
19 returning content
20 )
21 from
22 dual
23 .
SCOTT> /

XMLQUERY('XQUERYVERSION"1.0";DECLARENAMESPACEMO="HTTP://192.168.1.20/MY_NAMESPAC
--------------------------------------------------------------------------------
<result><greeting>Hello, 03-1234-5555</greeting><greeting>Hello, 090-4321-7878</
greeting><greeting>Hello, 070-7777-8798</greeting><greeting>Hello, 06-1234-5555<
/greeting><greeting>Hello, 06-6860-0001</greeting><greeting>Hello, 090-6666-7878
</greeting><greeting>Hello, 080-9999-8798</greeting><greeting>Hello, 06-6860-000
1</greeting><greeting>Hello, 090-0066-0108</greeting><greeting>Hello, 090-3020-2
897</greeting></result>


SCOTT>

SQL/XMLやXQueryを実行する場合には、SET SQLTERMINATOR OFFを使って ";"を無視させた方が便利で簡単ですね。

| | コメント (0) | トラックバック (0)

2007年12月13日 (木)

Oracle de XMLDB #13

● バックナンバー
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4
Oracle de XMLDB #5 - Oracle11g環境再構築完了
Oracle de XMLDB #6 - Linux x86版再び。
Oracle de XMLDB #7 - 何かが違う!?
Oracle de XMLDB #8 - またまた少々脱線
Oracle de XMLDB #9 - またまた少々脱線の続き
Oracle de XMLDB #10 - 三度脱線
Oracle de XMLDB #11 - 三度脱線のおまけ
Oracle de XMLDB #12


さて、前回SQL*PlusのXQueryコマンドのXQuery宣言ではversion及びencodingが指定できなかったり、先頭行にコメントが書けなかったがSQL/XMLのxmlquery()関数内ではどうなのか確認しておく。
環境はいつものとおり、Oracle11g EE R1 11.1.0.6.0 for Linux x86へMacOSXのTerminalからssh接続して行った。

Last login: Thu Dec 13 07:54:08 on console
Welcome to Darwin!
G5Server:˜ discus$ su - oracle
Password:
G5Server:˜ oracle$ ssh oracle@corydoras
oracle@corydoras's password:
Last login: Wed Dec 12 21:21:43 2007 from 192.168.1.19
[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 木 12月 13 17:03:36 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

> conn scott/tiger
接続されました。
SCOTT> l
1 select
2 xmlquery(
3 'xquery version "1.0" encoding "utf-8";
4 declare namespace mo = "http://192.168.1.20/my_namespace";
5 declare function mo:phoneNumber($phone)
6 {
7 $phone/text()
8 };
9 (: Query body :)
10 <result>
11 {
12 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
13 return
14 <greeting>
15 { fn:concat("Hello, ", mo:phoneNumber($i)) }
16 </greeting>
17 }
18 </result>'
19 returning content
20 )
21 from
22 dual
SCOTT> /
dual
*
行22でエラーが発生しました。:
ORA-19284: バージョン宣言におけるエンコーディング指定はサポートされていません

xmlquery()関数では、SQL*PlusのXQueryコマンドとは異なりencodingは指定できないがversionだけは指定できるようだ。

SCOTT> edit
file afiedt.bufが書き込まれました。

1 select
2 xmlquery(
3 'xquery version "1.0";
4 declare namespace mo = "http://192.168.1.20/my_namespace";
5 declare function mo:phoneNumber($phone)
6 {
7 $phone/text()
8 };
9 (: Query body :)
10 <result>
11 {
12 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
13 return
14 <greeting>
15 { fn:concat("Hello, ", mo:phoneNumber($i)) }
16 </greeting>
17 }
18 </result>'
19 returning content
20 )
21 from
22* dual
SCOTT> /

XMLQUERY('XQUERYVERSION"1.0";DECLARENAMESPACEMO="HTTP://192.168.1.20/MY_NAMESPAC
--------------------------------------------------------------------------------
<result><greeting>Hello, 03-1234-5555</greeting><greeting>Hello, 090-4321-7878</
greeting><greeting>Hello, 070-7777-8798</greeting><greeting>Hello, 06-1234-5555<
/greeting><greeting>Hello, 06-6860-0001</greeting><greeting>Hello, 090-6666-7878
</greeting><greeting>Hello, 080-9999-8798</greeting><greeting>Hello, 06-6860-000
1</greeting><greeting>Hello, 090-0066-0108</greeting><greeting>Hello, 090-3020-2
897</greeting></result>


SCOTT>


ではSQL*PlusのXQueryコマンドでは先頭行がコメントである場合、XQueryとは解釈されずSQL文として解釈されてしまっていたがxmlquery()関数ではそのような書き方でも問題はない。
SQL*PlusのXQueryコマンドは、XQuery宣言ではなく、SQL*PlusのXQueryコマンドだということを忘れないようにしたい。(混乱しそうだが。。。。)

SCOTT> edit
file afiedt.bufが書き込まれました。

1 select
2 xmlquery(
3 '(: コメントを先頭に :)
4 xquery version "1.0";
5 declare namespace mo = "http://192.168.1.20/my_namespace";
6 declare function mo:phoneNumber($phone)
7 {
8 $phone/text()
9 };
10 (: Query body :)
11 <result>
12 {
13 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
14 return
15 <greeting>
16 { fn:concat("Hello, ", mo:phoneNumber($i)) }
17 </greeting>
18 }
19 </result>'
20 returning content
21 )
22 from
23* dual
SCOTT> /

XMLQUERY('(:コメントを先頭に:)XQUERYVERSION"1.0";DECLARENAMESPACEMO="HTTP://192.
--------------------------------------------------------------------------------
<result><greeting>Hello, 03-1234-5555</greeting><greeting>Hello, 090-4321-7878</
greeting><greeting>Hello, 070-7777-8798</greeting><greeting>Hello, 06-1234-5555<
/greeting><greeting>Hello, 06-6860-0001</greeting><greeting>Hello, 090-6666-7878
</greeting><greeting>Hello, 080-9999-8798</greeting><greeting>Hello, 06-6860-000
1</greeting><greeting>Hello, 090-0066-0108</greeting><greeting>Hello, 090-3020-2
897</greeting></result>


SCOTT>

| | コメント (0) | トラックバック (0)

Oracle de XMLDB #12

● バックナンバー
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4
Oracle de XMLDB #5 - Oracle11g環境再構築完了
Oracle de XMLDB #6 - Linux x86版再び。
Oracle de XMLDB #7 - 何かが違う!?
Oracle de XMLDB #8 - またまた少々脱線
Oracle de XMLDB #9 - またまた少々脱線の続き
Oracle de XMLDB #10 - 三度脱線
Oracle de XMLDB #11 - 三度脱線のおまけ


DB Magazineに連載されていたXMLマスター実践講座 プロフェッショナル(DB)試験対応 第2回 XQueryの概要にあるLIST1:サンプルのXqueryとほぼ同じクエリをOracle11g R1(Linux x86)のSQL*Plusで試してみる。

Last login: Wed Dec 12 22:18:10 on ttyp1
Welcome to Darwin!
G5Server:˜ discus$ su - oracle
Password:
G5Server:˜ oracle$
G5Server:˜ oracle$ ssh oracle@corydoras
oracle@corydoras's password:
Last login: Wed Dec 12 23:03:58 2007 from 192.168.1.19
[oracle@corydoras ˜]$
[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 水 12月 12 23:04:46 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

●まず、addresslist.xmlファイルをOracle XDBリポジトリへ事前に登録しておく。
簡単なXQueryで問い合わせ内容を確認しておきましょう。

> conn scott/tiger
接続されました。
SCOTT>
SCOTT> set long 4000
SCOTT> l
1 xquery
2 for $i in fn:doc("/public/scott/xml/addresslist.xml")
3 return $i
SCOTT> /

Result Sequence
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?><アドレスブック><連絡先><氏名><姓>赤坂</姓
><名>元</名></氏名><住所/><メール><アドレス 区分="プライベート">G.Akasaka@coldma
il.jp</アドレス><アドレス 区分="携帯">G.Akasaka@hardbank.ne.jp</アドレス><アドレ
ス 区分="携帯">G.Akasaka@dokodemo.ne.jp</アドレス></メール><電話><電話番号 区分=
"自宅">03-1234-5555</電話番号><電話番号 区分="携帯">090-4321-7878</電話番号><電
話番号 区分="携帯">070-7777-8798</電話番号></電話></連絡先><連絡先><氏名><姓>麻
布</姓><名>太郎</名></氏名><住所/><メール><アドレス 区分="会社">T.Azabu@taro.co.
jp</アドレス><アドレス 区分="プライベート">T.Azabu@coolmail.jp</アドレス><アドレ
ス 区分="携帯">T.Azabu@a_phone.ne.jp</アドレス><アドレス 区分="携帯">T.Azabu@bu.
ne.jp</アドレス></メール><電話><電話番号 区分="自宅">06-1234-5555</電話番号><電
話番号 区分="会社">06-6860-0001</電話番号><電話番号 区分="携帯">090-6666-7878</
電話番号><電話番号 区分="携帯">080-9999-8798</電話番号></電話></連絡先><連絡先><
氏名><姓>代々木</姓><名>武</名></氏名><住所/><メール><アドレス 区分="プライベー
ト">Y.Takeshi@ba-net.ne.jp</アドレス><アドレス 区分="携帯">Y.Takeshi@dokodemo.ne
.jp</アドレス><アドレス 区分="携帯">Y.Takeshi@bu.ne.jp</アドレス></メール><電話>
<電話番号 区分="会社">06-6860-0001</電話番号><電話番号 区分="携帯">090-0066-0108
</電話番号><電話番号 区分="携帯">090-3020-2897</電話番号></電話></連絡先></アド
レスブック>

● 本来なら問題ない構文から試してみると。。。

SCOTT> (: サンプル :)
2 xquery version "1.0" encoding "utf-8";
(: サンプル :)
*
行1でエラーが発生しました。:
ORA-00928: SELECTキーワードがありません。

あ〜〜〜、XQueryのコメントとして解釈されているのかと思ったが、SQL*PlusではXQueryのコメントから始めることはできないようだ。

NOTE 1)
SQL*PlusでXQueryを利用する場合、XQueryのコメント文から入力してしまうと通常のSQL文と判断してしてしまうので要注意!

NOTE 2)
SQL*Plusでは、";"は文を実行するという意味があるのでXQueryのPrologで入力してしまうとそこまで入力したXQueryを解析、実行してしまうので要注意!

SQL*PLusでXqueryを入力する際のちょっとしたテクニックとして、一旦前述のように入力後SQL*Plusのeditコマンドでviなどを起動し編集すればこの問題は回避できる。以下はeditコマンドを利用してviで入力した。

SCOTT> edit
file afiedt.bufが書き込まれました。

1 (: サンプル :)
2 xquery version "1.0" encoding "utf-8";
3 declare namespace mo = "http://192.168.1.20/my_namespace";
4 declare function mo:phoneNumber($phone)
5 {
6 $phone/text()
7 };
8 (: Query Body :)
9 <result>
10 {
11 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
12 return
13 <greeting>
14 { fn:concat( "Hello, ", mo:phoneNumber($i)) }
15 </greeting>
16 }
17* </result>
18 /
SP2-0552: バインド変数"CONCAT"が宣言されていません。

やはり、XQueryのコメント(::)から開始するとSQL文だと判断されてしまうようだ。


XQueryコマンドの前にあるXQueryのコメントを削除する。XQueryとしては正しいのだが、SQL*Plusでは別のエラーが発生する。
以下のエラーメッセージから version "1.0" の部分が文法エラーとされてしまっている。恐らくencodeingも文法エラー扱いになるだろう。

SCOTT> edit
file afiedt.bufが書き込まれました。

1 xquery version "1.0" encoding "utf-8";
2 declare namespace mo = "http://192.168.1.20/my_namespace";
3 declare function mo:phoneNumber($phone)
4 {
5 $phone/text()
6 };
7 (: Query Body :)
8 <result>
9 {
10 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
11 return
12 <greeting>
13 { fn:concat( "Hello, ",mo:phoneNumber($i)) }
14 </greeting>
15 }
16* </result>
SCOTT> /
ERROR:
ORA-19114: XPST0003 - XQuery式を解析中にエラーが発生しました: LPX-00801:
XQuery syntax error at '"1.0"'
1 version "1.0" encoding "utf-8";
- ^

ということで、versionとencodingを削除してみると、わ〜〜、パチパチ。上手くできました。
XQueryの文法では正しくてもSQL*PlusやOracle11gの実装により文法エラーとされてしまうケースもあるので、Oracle11gでXMLマスタープロフェッショナル(DB)の勉強をする際には要注意。

SCOTT> edit
file afiedt.bufが書き込まれました。

1 xquery
2 declare namespace mo = "http://192.168.1.20/my_namespace";
3 declare function mo:phoneNumber($phone)
4 {
5 $phone/text()
6 };
7 (: Query Body :)
8 <result>
9 {
10 for $i in fn:doc("/public/scott/xml/addresslist.xml")//電話番号
11 return
12 <greeting>
13 { fn:concat("Hello, ",mo:phoneNumber($i)) }
14 </greeting>
15 }
16* </result>
SCOTT> /

Result Sequence
--------------------------------------------------------------------------------
<result><greeting>Hello, 03-1234-5555</greeting><greeting>Hello, 090-4321-7878</
greeting><greeting>Hello, 070-7777-8798</greeting><greeting>Hello, 06-1234-5555<
/greeting><greeting>Hello, 06-6860-0001</greeting><greeting>Hello, 090-6666-7878
</greeting><greeting>Hello, 080-9999-8798</greeting><greeting>Hello, 06-6860-000
1</greeting><greeting>Hello, 090-0066-0108</greeting><greeting>Hello, 090-3020-2
897</greeting></result>





Ang?lique Kidjo - Djin Djin - Gimme Shelter

話はがらりと変わり、昨日はAngelique Kidjoライブご招待へ当選したので、ウチのおチビちゃんのお守りは奥さんに任せてdrmarさんをとブルーノート東京へ(久々だな〜)

曲目全ては覚えていないのだが、

Gimme Shelterをはじめ (アルバムでは、Joss Stone Joss Stone - Introducing Joss Stone
をフィーチャーしている)アルバム Djin Djinからの曲。私もdrmarさん同様、全く知らなかったアーティストなのだが、グラミー賞には過去5回ノミネートされたことがある実力派。西アフリカはペナン共和国出身。その影響だろうか、日本はもう冬なのだが、曲は太陽を感じるような曲が多い。

アルバム Djin Djinでは、ビーター・ガブリエル、カルロス・サンタナ、ジョス・ストーンなど多彩なゲストをフィーチャーしている。

YouTube - Gimme Shelter(Feat. Joss Stone)
YouTube - Africa Calling
YouTube - Voodoo Child
YouTube - Tumba


Angelique_kidjo

| | コメント (0) | トラックバック (0)

2007年12月 7日 (金)

Oracle de XMLDB #11 - 三度脱線のおまけ

三度脱線したついでに・・・・

HTTPURITYPE型User-Agentはどうなっているのだろうか?  

そう思ったらやった方がはやいですね!!  

ということで、我が家のMac OS X server Leopard 10 Client版で普段は眠っているApacheを起動、Mac De OracleのAtomを配置して試してみた。

192.168.1.19 - - [07/Dec/2007:00:43:46 +0900] "GET /feed/mac_de_oracle_atom.xml HTTP/1.1" 200 13811 "-" "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/419.3 (KHTML, like Gecko) Safari/419.3"
192.168.1.19 - - [07/Dec/2007:00:54:57 +0900] "GET /feed/mac_de_oracle_atom.xml HTTP/1.1" 304 - "-" "AppleSyndication/54"
192.168.1.20 - - [07/Dec/2007:01:05:25 +0900] "GET /feed/mac_de_oracle_atom.xml HTTP/1.1" 200 14644 "-" "-"

見ての通り、最後のログがOracleのHTTPURITYPE型でアクセスした場合のログなのだが、User-Agentは設定されていない!

| | コメント (0) | トラックバック (0)

2007年11月28日 (水)

Oracle de XMLDB #10 - 三度脱線

XMLマスタープロフェッショナル(データベース)の開始も間近だし、「XMLマスター:プロフェッショナル(データベース)」再受験無料プログラム」もあるので試験勉強を中心にと思いつつ、気になることがあると試したくなる性分なので、三たび脱線。
SQL/XMLのCOLUMNS句も確認しておこうかなと。。いうことで。。。

まずACLの確認。(今回は、OTN-JフォーラムのFEEDを材料にしてみた。。)

もしACLが作成されていない、又は、接続先ホストが割り当てられていない場合はdbms_network_acl_adminパッケージ定義/割当してくださいませ。

SYS> select acl,host from dba_network_acls;

ACL HOST
---------------------------------------- --------------------------------------------------
/sys/acls/feeds.xml otn.oracle.co.jp

SYS> select principal,acl,privilege,is_grant from dba_network_acl_privileges
2 where principal='SCOTT';

PRINCIPAL ACL PRIVILE IS_GRANT
---------- ---------------------------------------- ------- --------------------
SCOTT /sys/acls/feeds.xml connect true
SCOTT /sys/acls/feeds.xml resolve true

SYS>
SYS> conn scott/tiger
接続されました。
SCOTT> l
1 select *
2 from
3 xmltable(
4 xmlnamespaces('http://www.jivesoftware.com/xmlns/jiveforums/rss' as "jf"),
5 'for $i in /rss/channel/item
6 return
7 <rss>{$i/title}{$i/jf:creationDate}{$i/jf:author}{$i/jf:replyCount}{$i/link}</rss>'
8 passing httpuritype('http://otn.oracle.co.jp/forum/rss/rssmessages.jspa?categoryID=2').getXML()
9 columns
10 title varchar2(100) path '/rss/title',
11 pubDate varchar2(30) path '/rss/jf:creationDate',
12 author varchar2(50) path '/rss/jf:author',
13 replyCount integer path '/rss/jf:replyCount',
14 link varchar2(200) path '/rss/link'
15 )
16 where
17 title like '%日付のインクリメント%'
18 order by
19* substr(pubdate,instr(pubdate,','))
SCOTT> /

TITLE PUBDATE AUTHOR REPLYCOUNT LINK
---------------------------------------- ------------------------------ -------------------- ---------- ------------------------------------------------------------------------------------------
日付のインクリメント 火, 27 11 2007 18:02:44 +0900 tahakoda 2 http://otn.oracle.co.jp/forum/thread.jspa?messageID=35020441&tstart=0#35020441
Re: 日付のインクリメント 火, 27 11 2007 20:35:31 +0900 茶太郎 0 http://otn.oracle.co.jp/forum/thread.jspa?messageID=35020443&tstart=0#35020443
Re: 日付のインクリメント 水, 28 11 2007 06:44:47 +0900 discus 0 http://otn.oracle.co.jp/forum/thread.jspa?messageID=35020450&tstart=0#35020450

SCOTT>

尚、HTTPURITYPE型でマルチバイトを含むXML文書を参照する場合はXML文書の文字エンコーディングと同じデータベースキャラクタセットでないと文字化け?の影響と思われるXMLパースエラーが発生するので要注意。


前々回のエントリにも追記したのだが・・・・

XML文書の文字エンコーディングとデータベースキャラクタセットが異なる場合は、

Mac De PL/SQL RSS Reader #3

のようにUTL_HTTPパッケージを利用して対処することもできるのでどうしても文字エンコーディングが異なる環境で行うなら自作でユーザ定義型を作るしか無さそう。。。。

いまのところXMLDBなどを利用して各種Webサービスと連携するのならデータベースキャラクタセットはAL32UTF8にしておくのがいちばんよさそうだ。(オラクルさんも新規データベースはAL32UTF8を推奨しているし。。

| | コメント (0) | トラックバック (0)

2007年11月25日 (日)

Oracle de XMLDB #9 - またまた少々脱線の続き

子持ちのDiscusとなって初投稿。なにげに左の画像も変えてみたり。。。 :)

Discusという魚、ディスカスミルクで子供を育てるんですよ!

discusは一夫一婦制で子育ては両親協力して行うんです。
孵化後数日し幼魚が親のまわりを泳ぎ始めると
親discusの体からは栄養のある分泌物が出し始めます。
それがディスカスミルク!

ディスカスミルクを飲むために親の体に群がる子discusたち。ほんとにかわいいです。


前置きはこれくらいにして、本題へ。

前回はHttpUriType型やその型を利用している(と思われる)DBMS_PARSER.PARSE(parser,uri)ファンクションでは参照するXML文書の文字エンコーディングとデータベースキャラクタセットが異なる場合、文字化けの影響でパースエラーが発生するというということだった。(Oracle10g R1/R2それにOracle11g R1でも)

その最後で。「・・・略・・・。上記のコードをそのまま実行しようとするとエラーになる。」と書いていたのだが、覚えているだろうか?

そのエラーは以下のような場合でも発生する。

以下、ウチの奥さんのブログのFEED(ATOM version=0.3)を利用して試してみた。(Oracle11g以降では以下のようにセキュリティが強化されている。)

Last login: Thu Nov 22 21:58:23 on ttyp1
Welcome to Darwin!
G5Server:˜ oracle$
G5Server:˜ oracle$ ssh oracle@corydoras
oracle@corydoras's password:
Last login: Thu Nov 22 22:39:56 2007 from 192.168.1.19
[oracle@corydoras ˜]$
[oracle@corydoras ˜]$
[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 木 11月 22 22:46:51 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

SCOTT> l
1 SELECT *
2 FROM
3 XmlTable(
4 'for $i in //*
5 return $i'
6 PASSING HttpUriType('http://atsu-log.way-nifty.com/today_s_menu/atom.xml').getXML()
7* )
SCOTT> /
PASSING HttpUriType('http://atsu-log.way-nifty.com/today_s_menu/atom.xml').getXML()
*
行6でエラーが発生しました。:
ORA-29273: HTTPリクエストに失敗しました ORA-06512:
"SYS.UTL_HTTP", 行1674
ORA-24247: アクセス制御リスト(ACL)によりネットワーク・アクセスが拒否されました ORA-06512: "SYS.HTTPURITYPE",
行34
ORA-06512: "SYS.HTTPURITYPE", 行97



詳しくはマニュアルを読んでもらうとして、HttpUriType型でネットワークアクセスを許可してみる。

マニュアル(英語)
Managing Fine-Grained Access to External Network Services
Using DBMS_NETWORK_ACL_ADMIN

● まず、現状確認

DBA_NETWORK_ACLSビューとDBA_NETWORK_ACL_PRIVILEGESビューという2つのディクショナリビューで確認する。
以下の結果からも分かるように、外部ネットワークへのアクセスを許可するACLなど一切定義されていない。

SYS> select acl,host from dba_network_acls;

レコードが選択されませんでした。

SYS> select principal,acl,privilege,is_grant from dba_network_acl_privileges where principal = 'SCOTT';

レコードが選択されませんでした。

SYS>

● ACLを作成し、参照先ホストや必要な権限を付与する。

Managing Fine-Grained Access Control to External Network Services from the Databaseに書かれているように、ACLを作成後connect及び、resolve権限をSCOTTユーザへ付与し、そのACLに対してアクセス先のホストを割り当てる。

注)コミットをお忘れなく!
SYS> BEGIN
2 DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(
3 acl=> 'feeds.xml',
4 description=>'acl for any feeds',
5 principal=> 'SCOTT',
6 is_grant=> true,
7 privilege=> 'connect'
8 );
9 DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(
10 acl=> 'feeds.xml',
11 principal=>'SCOTT',
12 is_grant=>true,
13 privilege=>'resolve'
14 );
15 DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(
16 acl=>'feeds.xml',
17 host=> 'atsu-log.way-nifty.com'
18 );
19 COMMIT;
20 END;
21 /

PL/SQLプロシージャが正常に完了しました。

SYS> select acl,host from dba_network_acls;

ACL HOST
---------------------------------------- --------------------------------------------------
/sys/acls/feeds.xml atsu-log.way-nifty.com

SYS> select principal,acl,privilege,is_grant from dba_network_acl_privileges
2 where principal='SCOTT';

PRINCIPAL ACL PRIVILE IS_GRANT
---------- ---------------------------------------- ------- --------------------
SCOTT /sys/acls/feeds.xml connect true
SCOTT /sys/acls/feeds.xml resolve true

SYS>


● 再度、試してみる。

お〜〜〜。上手く行きました。
NOTE:
Oracle10g R2でも同じことはできますがACLで保護されていないので前述の手順は無くても行えます。

SCOTT> l
1 SELECT *
2 FROM
3 XmlTable(
4 'for $i in //*
5 return $i'
6 PASSING HttpUriType('http://atsu-log.way-nifty.com/today_s_menu/atom.xml').getXML()
7* )
SCOTT> /

COLUMN_VALUE
--------------------------------------------------------------------------------
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/d
c/elements/1.1/"><title>今日のゴハン</title><link rel="alternate" type="text/htm
l" href="http://atsu-log.way-nifty.com/today_s_menu/"/><id>tag:app.cocolog-nifty
.com,2003:weblog-121882</id><link rel="service.post" type="application/x.atom+xm
l" href="http://app.cocolog-nifty.com/t/atom/weblog/blog_id=121882" title="今日
のゴハン"/><modified>2007-11-24T11:17:10Z&;t/modified><tagline>今日もごちそうさま
。(ぺこり)</tagline><generator url="http://www.typepad.com/" version="1.0">

・・・・・中略・・・・

<br xmlns="http://www.w3.org/1999/xhtml"/>
<p xmlns="http://www.w3.org/1999/xhtml">今日は夕方近くに散歩に出かけたら北風で手
が冷たくなったダーリン。<br/>
この麻婆豆腐のおかげで手も温かくなり、さらに汗だくになるくらいカプサイシン効果を
<br xmlns="http://www.w3.org/1999/xhtml"/>

197行が選択されました。

あ〜〜〜っ。長いのでちゃんと絞り込んでみましょう。

SCOTT> l
1 SELECT *
2 FROM
3 XmlTable(
4 'for $i in //entry/title
5 return $i/text()'
6 PASSING HttpUriType('http://atsu-log.way-nifty.com/today_s_menu/atom.xml').getXML()
7* )
SCOTT> /

レコードが選択されませんでした。

これまた失礼。名前空間を指定し忘れたのでヒットしなかったようですね。
奥さんのブログのATOM FEEDは、version="0.3"で"1.0"のATOMとは名前空間が違う。。。ソースを確認して。。。

はい、できました〜〜。

SCOTT> l
1 SELECT *
2 FROM
3 XmlTable(
4 XmlNamespaces(
5 'http://purl.org/dc/elements/1.1/' as "dc",
6 default 'http://purl.org/atom/ns#'
7 ),
8 'for $i in //entry/title
9 return $i/text()'
10 PASSING HttpUriType('http://atsu-log.way-nifty.com/today_s_menu/atom.xml').getXML()
11* )
SCOTT> /

COLUMN_VALUE
--------------------------------------------------------------------------------
酢豚
スイートポテト
白身魚のホイル焼き
ミネストローネ
一足お先に乾杯!
おいなりさん
ミルク寒天
そぼろご飯
産まれました♪
麻婆豆腐

10行が選択されました。

SCOTT>

Oracle11g R1以降、Oracleデータベース内から外部のWebサービスを利用する際にはACLによる細かなアクセス制御が必要になるので忘れないようにしないと! => 備忘録。

ということで2回連続で脱線してしまったが、次回からはまたOracle XML DBのXQueryを使っていろいろと試してみるか。

| | コメント (0) | トラックバック (0)

2007年11月22日 (木)

Oracle de XMLDB #8 - またまた少々脱線

久々にOracle11gのXML DBネタなのだが、XQueryなどのXMLマスタープロフェッショナル(データベース)絡みのネタからはまた脱線。SQL/XMLネタを一つ。

以前、Oracle10g R1/R2上でRSS FEEDをPL/SQLで取得してOracle Application Expressで表示なんてことをやっていた。
(33回も連載してたっけ。。。。)

Mac De PL/SQL RSS Reader #1
Mac De PL/SQL RSS Reader #2

それらのエントリで、参照するXML文書の文字エンコーディングとデータベースキャラクタセットが異なると文字化けを起こしてしまうHttpUriType型の仕様?のことを書いていたのだが、先日リリースされたOracle11g R1ではどうなったのか?


確かめてみた! 

まずは、SQL/XMLを利用した例。(以下は、Oracle11g R1 for Linux x86を利用。)

XML文書の文字エンコーディングはUTF-8、Oracleデータベースのキャラクタセットは、JA16SJISTILDE。

SCOTT> r
1 select *
2 from
3 xmltable(
4 'for $i in //*
5 return $i'
6 passing httpuritype('http://discus-hamburg.cocolog-nifty.com/test/atom.xml').getXML()
7* )
passing httpuritype('http://discus-hamburg.cocolog-nifty.com/test/atom.xml').getXML()
*
行6でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 30
中にエラーが発生しました
ORA-06512: "SYS.XMLTYPE", 行5
ORA-06512: "SYS.HTTPURITYPE", 行97


SCOTT>


あ〜〜〜〜やっぱり、ダメね〜。上記はXML文書のパースエラーとして現れているのだが、その原因は文字化けなのである。


XML文書とOracleデータベースのキャラクタセットが異なる場合(前述の例では、UTF-8とSJIS)にはHttpUriType型を利用せず、UTL_HTTPパッケージを利用し、

UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');

のようにすることで文字化けせずにXML文書を取込むことができる。
尚、XML文書、データベースキャラクタセットが同一である場合(XML文書がUTF-8でデータベースキャラクタセットがAL32UTF8のような場合)には文字化けは発生しない。これは私個人の想像なのだが、HttpUriType型が裏でHTTP通信する際に利用する文字エンコーディングはデータベースキャラクタセットから導出しているのだと思われる。今のところHttpUriType型には文字エンコーディングは指定できないのでオラクルさんが方針を変えない限り文字化けの回避策は前述の2つしかないだろう。

2007/11/28追記
もしどうしてもXML文書の文字エンコーディングとデータベースキャラクタセットが異なる環境でHTTPURITYPE型を使いたいということであれば、代替策としてUTL_HTTPパッケージを利用したユーザ定義型を作成すれば可能かもしれない。
(あくまで推測。。あとで試してみるか=>TODO)

以前、DBMS_XMLPARSER.PARSE(parser, uri)を使ってFEEDを直接参照した場合も同様のエラーだったが、UTL_HTTPパッケージを利用して文字化けを回避した。
以下URL参照のこと。(下記のエントリの内容はOracle10g R1/R2で試したものです。)

Mac De PL/SQL RSS Reader #3

SQL/XML機能が充実してきたので今後はあまり使わなくなるかもしれないが、次いでなのでDBMS_XMLPARSER.PARSER(parser,uri)でも試してみた。
DBMS_XMLPARSER.PARSER(parser, uri)でもHttpUriType型を利用しているだろうから結果は同じはずだ。
(また、XMLマスタープロフェッショナル(データベース)ネタからは離れてく〜〜。w)

以前作成したコードを少々手直してOracle11gで実行!(Oracle SQL Developer for MacOSXを利用した)
Xmldb8_jdev


● ソース

CREATE OR REPLACE PROCEDURE GET_FEED(i_url IN VARCHAR2)
AS
v_url VARCHAR2(32767);
v_myParser DBMS_XMLPARSER.Parser;
v_rssDoc DBMS_XMLDOM.DomDocument;
v_xml XMLTYPE;

PROCEDURE println(str IN VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(str);
END;

PROCEDURE println
(
i_text IN CLOB
)
IS
v_tempStr VARCHAR(32767);
v_numOfPieces PLS_INTEGER;
BEGIN
v_numOfPieces := CEIL(LENGTH(i_text)/1000);
FOR i IN 1..v_numOfPieces LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(i_text, ((i-1)*1000), 1000));
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'println(CLOB) internal procedure:'
|| sqlerrm()
);
RAISE;
END println;

--****************************************************************************
--* Main
--****************************************************************************
BEGIN
DBMS_OUTPUT.ENABLE(200000);
println('begin...');


v_url := i_url;
IF v_url IS NULL THEN
RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。');
END IF;

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSE(v_myParser, v_url);
v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
println('DBMS_XMLPARSERバージョン:'||DBMS_XMLPARSER.GETRELEASEVERSION());
println('DBMS_XMLDOMバージョン :'||DBMS_XMLDOM.GETVERSION(v_rssDoc));
println(' ');
println('=== パース済みDOMから取得したRSSソース ===');
println(XmlType.GETCLOBVAL(v_xml));
println('====================');
println(' ');
DBMS_XMLPARSER.FREEPARSER(v_myParser);

println('...End');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Main Procedure:'
|| sqlerrm()
);
RAISE;

END GET_FEED;


● 結果

RSS FEED(UTF-8)をデータベースキャラクタセット(JA16SJISTILDE)から取込んだ場合。
Connecting to the database Oracle11g R1 Scott(leaffish) - JA16SJISTILDE.
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 30
中にエラーが発生しました
ORA-06512: "SCOTT. GET_FEED", 行161
ORA-06512: 行6
begin...
Main Procedure:ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 30
中にエラーが発生しました
Process exited.
Disconnecting from the database Oracle11g R1 Scott(leaffish) - JA16SJISTILDE.


RSS FEED(UTF-8)をデータベースキャラクタセット(AL32UTF8)から取込んだ場合。文字エンコーディングが同じ場合は問題なし!
ところで、Oracle11g R1でも、DBMS_XMLPARSERのパージョンは10.1.0.2.0なのね〜。(^^;;;

Connecting to the database Oracle11g R1 Scott(guppy) - AL32UTF8.
begin...
DBMS_XMLPARSERバージョン:10.1.0.2.0
DBMS_XMLDOMバージョン :1.0

=== パース済みDOMから取得したRSSソース ===
<?xml version="1.0" encoding="utf-8"?>

<feed xmlns="http://www.w3.org/2005/Atom">
<title>Mac De Oracle</title>
<link rel="alternate" type="text/html" href="http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/" />
<link rel="service.post" type="application/x.atom+xml" href="http://app.cocolog-nifty.com/t/atom/weblog/blog_id=121907" title="Mac De Oracle" />
<id>tag:app.cocolog-nifty.com,2003:weblog-121907</id>
<updated>2007-11-19T09:16:39Z</updated>


・・・・中略・・・・


<summary>前回、何かが違うと感じたと書いたがそれはなにか? 実はwhitespaceに関す...</summary>
<author>
<name>discus</name>
</author>
<category term="Linux" />
<category term="Oracle" />
<category term="Oracle Database 11g" />
<category term="XML" />




</entry>

</feed>
====================

...End
Process exited.
Disconnecting from the database Oracle11g R1 Scott(guppy) - AL32UTF8.


尚、Oracle11g R1ではセキュリティが強化されている。(Oracle10g R2以前のセキュリティレベルにもできるようだが。。)上記のコードをそのまま実行しようとするとエラーになる。

ということで、セキュリティ関連も含めて続きは次回ということで。


おまけ

以下の資料はSQL/XMLって何? ってとこからスタートする方にはよいかも..。
オープンソースカンファレンス2007 .DBの資料「XQuery、XPath 及び SQL / XML に関する標準化動向と今後の取組み状況」 (PDF)

以下のサイトにはSQL/XML関連の情報がいろいろ(英語です。)
SQLX.org

その他、OTN-Jなどにもあったかも。。。(未確認)

| | コメント (0) | トラックバック (0)

2007年10月31日 (水)

Oracle de XMLDB #7 - 何かが違う!?

前回、何かが違うと感じたと書いたがそれはなにか? 実はwhitespaceに関することだった。(OTN-Jへ投稿したものの、XMLの部屋の状況を見ているだけに、レスは付かないかもしれないな〜と思いつつも、ダメもとで、とりあえず尋ねてみた。)


バックナンバー:
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4 - fizzbuzzから
Oracle de XMLDB #5 - Oracle11g環境再構築完了
Oracle de XMLDB #6 - Linux x86版再び。

前置きはこのくらいにして、
初めてこの違いに気付いたのはWindows環境で遊び始めたときだった。Windows環境ではデータベースキャラクタセットはAL32UTF8、SQL*Plusは当然ながらJA16SJISになっている。データベースキャラクタセットとClientのNLS_LANGが異なるとコード変換が発生して、XMLはUTF-8からSHIFT_JISへ変換されて帰ってくる。まあ、エンコードが違う程度なら驚かなかったと思うのだが、whitespace strip/preserveまで異なると、見た目が違うので、あれれ???? と驚いてしまったわけなのですよ。
Oracle10gでも似たような話はあったので理由は同じなのかもしれないですが・・

注)OTN-Jのフォーラムへ投稿した内容は、以降に記載した内容を再編集したものです。

まずは、XMLファイルの登録。(windows/Linux環境とも全く同じことをやってます。)
●test1.xml

<?xml version="1.0" encoding="UTF-8"?>
<テスト>
<内容>あいうえお</内容>
</テスト>

●test2.xml

<?xml version="1.0" encoding="UTF-8"?>
<test>
<content>abcdefg</content>
</test>

●上記XMLファイルを以下のようにしてXMLリポジトリへ登録。

SCOTT> l
1 declare
2 r boolean;
3 begin
4 r := dbms_xdb.createresource(
5 '/public/scott/xml/test1.xml',
6 bfilename('SCOTT_XMLDIR','test1.xml'),
7 nls_charset_id('AL32UTF8'));
8 r := dbms_xdb.createresource(
9 '/public/scott/xml/test2.xml',
10 bfilename('SCOTT_XMLDIR','test2.xml'),
11 nls_charset_id('AL32UTF8'));
12* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT> commit;

コミットが完了しました。


● Windows版Oracle11g(データベースキャラクタセット:AL32UTF8, NLS_LANG=japanese_japan.JA16SJIS)
文字エンコーディング以外は元のXMLファイルを再現している。

SCOTT> xquery
2 let $d := fn:doc("/public/scott/xml/test1.xml")
3 return $d
4 /

Result Sequence
------------------------------------------------------------------------------

<?xml version="1.0" encoding="SHIFT_JIS"?>
<テスト>
<内容>あいうえお</内容>
</テスト>


SCOTT> xquery
2 let $d := fn:doc("/public/scott/xml/test2.xml")
3 return $d
4 /

Result Sequence
------------------------------------------------------------------------------

<?xml version="1.0" encoding="SHIFT_JIS"?>
<test>
<content>abcdefg</content>
</test>

● Linux版Oracle11g(データベースキャラクタセット;AL32UTF8、NLS_LANG=japanese_japan.AL32UTF8)
文字エンコーディングは元のXMLファイルを再現しているが、whitespaceは取り除かれている。

SCOTT> l
1 xquery
2 let $d := fn:doc("/public/scott/xml/test1.xml")
3* return $d
SCOTT> /

Result Sequence
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?><テスト><内容>あいうえお</内容></テスト>

SCOTT> xquery
2 let $d := fn:doc("/public/scott/xml/test2.xml")
3 return $d
4 /

Result Sequence
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?><test><content>abcdefg</content></test>

SCOTT>


ということは、Linux環境であってもデータベースキャラクタセットとクライアントの文字エンコーディングが異なれば同じ結果になるのでは???

試してみた!

[oracle@corydoras ˜]$ export NLS_LANG=american_america.JA16SJISTILDE
[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on Mon Oct 29 22:45:09 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

> conn scott/tiger
Connected.
SCOTT> set long 4000
SCOTT> l
1 xquery
2 let $d := doc("/public/scott/xml/test2.xml")
3* return $d
SCOTT> /

Result Sequence
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="SHIFT_JIS"?>
<test>
<content>abcdefg</content>
</test>


XMLマスタープロフェッショナル(データベース)取得へ向けて勉強しようと思っていたのだが、なんだか、どんどん別な方向へ行っている気がするのでこの辺で止めておこうかと。
(XMLのデータの再現性という点についてはちょうどいいネタでしたけどね。。)

ちなみに、XQueryの勉強用には、結果が確認しやすくなるのでデータベースキャラクタセットとNLS_LANGのエンコードは変えておいたほういいかもしれないですね。

ということで、Windows版Oracle11gは不要なので即削除ということに。うちではLinux環境の方が便利なのでね。。。(明日にはOTN Professional版のOracle11gが届きそうなのでまた入れ直すだろうけど。。)

※尚、OTN-Jでレスが付いたらこのエントリに追記する予定。

| | コメント (0) | トラックバック (0)

2007年10月28日 (日)

Oracle de XMLDB #6 - Linux x86版再び。

Windows版 Oracle Database 11g R1でXMLDB環境を再構築し、再度XQueryで遊び始めたのだが。。。。Linux版のOracle11g のXMLDBとは何かが違う。。。。。・・・・・・・


バックナンバー:
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4 - fizzbuzzから
Oracle de XMLDB #5 - Oracle11g環境再構築完了

本当はXMLDBで遊びたいだけなのだが、、何となく気持ち悪い・・・・・

となれば、以前から計画していたLinux環境復活を先に! 

ということで、以前はOracle9i R2 for Linux x86Oracle10g R1 for Linux x86環境として利用していたToshiba Dynabook SS SX/210LNLW RAM:768MB - Turbolinux 8 Enterprise Server (United Linux 1.0)環境を潰し、CentOS5 + Oracle11g R1 for Linux x86環境として作り直して、その違いを確認してみようということに急遽決定!!!!

尚、Toshiba Dynabook SS SX/210LNLWは、FDもCD/DVDドライブも搭載していないのだが、FDブート可能なFDドライブさえあればLinuxのインストールは可能で、以前TurboLinux 8 Enterprise Serverをインストールした際もFDイメージからブートし、外付けCDドライブからインストールしたことがある。。。

今回はCentOS5をネットワークインストールし、その後Oracle11gをインストールしてみることにした。

Dynabook SS SX/210LNLWへ繋いだFDドライブはこれ。


尚、CentOS5にはFDイメージが無いということなので、CentOS3.8のFDイメージでブート。一旦、CentOS3.8をインストールしてからCentOS5をネットワークインストールでクリーンインストールするという方法を取った。

ありがたいことに、この方法を試してブログで公開されている方がいたので参考にさせてもらった。
(ありがとうございます。いろいろ調べる手間が省けて助かりました。)

● FDはあるけどCD-ROMドライブの無いノートPCに最新版Linuxをインストール(CentOS3.8)
ただ、私がインストールした際、以下の赤字部分を変えた。(それ以外は、前述のブログに書かれている通りで行えた。)
grub.confの編集
# vi /boot/grub/grub.conf

以下の項目を追加。
title CentOS 5.0 Install
root (hd0,0)
kernel /boot/centos/vmlinuz ramdisk_size=8192
initrd /boot/centos/initrd.img

● FDはあるけどCD-ROMドライブの無いノートPCに最新版Linuxをインストール2(CentOS5編)


では、Toshiba Dynabook SS SX/210LNLWでCentOS5が起動した画像を。
Cimg7335

ここまでできたら、Oracle Database 11gをインストールすればいい。手順は以前のエントリを
(尚、Oracle11gをインストールするためには最低1GBのメモリが推奨されているが、このDynabookに積めるメモリは最大768MBである為1280MBだが512MB一枚しかなかったので768MBと少なめ。OUIの物理メモリサイズに関する警告を無視することでインストールを行った。Swapが多くなりモタツキ感はあるもののOracle11gは無事にインストールできた。)

以下は、MacOSX TigerのxtermよりCentOS5(Dynabook SS SX/210)へssh接続して起動したOUIの画像。
Dynabook_ss_oracle11g

ということで、次回は、 何かが違う。。。と思った点について確認してみるか。

| | コメント (0) | トラックバック (0)

2007年10月25日 (木)

Oracle de XMLDB #5 - Oracle11g環境再構築完了

前回まで使っていたCentOS5上に構築したOracle Database 11g R1 EEは、ThinkPad R52の下取りということになり、仕方ないのでメモリが1GBしかないDual AthronMP 2800+のWindows XP Professional SP2という環境にOracle11g環境を再構築した。(Linux環境へはいずれ戻る予定)
OUIの操作はLinux/Unixいつ登場するのか不明だが??MacOSXでも同じ。1点違うところは、root.shなどの実行が事くらいなので、ここで改めてWindows版のOracle Database 11gのインストールについて書くつもりはないのだけれど、その様子だけはQuickTimeムービーで公開しておくことにした。(^^。

バックナンバー:
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?
Oracle de XMLDB #4 - fizzbuzzから


WindowsへOracleをインストールするのだが、そこは、Mac De Oracleですから、素直にWindowsに向うことは無いということは予想できますよね!?

ということで、VNCを使ってもいいのだが、今回は、マイクロソフトから提供されているRemote Desktop Connection(以下、RDC)を利用することにした。(尚、RDCは、IntelMacには未対応のようなのでご注意ください。)

Rdc_icon


RDCの設定でポイントになる点を幾つか。
リモートデスクトップのサイズはご自分のディスプレイに合わせてくださいね。

Rdc_setting1 

パフォーマンスタブをクリックして、ドロップダウンメニュの「LAN(10Mbps以上)」を選択。(これより遅い環境でお使いの場合にはそれなりの設定にしてくださいね。)
Rdc_setting2



もし、こんなエラーがでたら、Windowsのローカルセキュリティ設定を一時的に変更すればOK。
Rdc_connect_error

Rdc_win_local_security



RDC経由でOUIを起動したところ。 :-)
Rdc_connect_oui



(再生にはQuickTimeが必要です。)

約1.8MBでサウンドトラックなし。


次回は、XQuery再開予定。

| | コメント (0) | トラックバック (0)

2007年10月22日 (月)

Oracle de XMLDB #4

データベースマガジンでもXQuery1.0は"習うより慣れろ"なんて書いてあったので、使って覚えるのが一番いいだろうなということで前々回に環境を構築したのだが、予想外の展開で、なかなか思うように試す時間がとれない・・・、それでも何とか時間を作らなきゃね。ということでやっとその続き。  

バックナンバー:
Oracle de XMLDB #1
Oracle de XMLDB #2
Oracle de XMLDB #3 - Oracle10g XEではどうよ?


最初はFizzBuzzからやってみた。(笑) さずがに、Hello Worldじゃつまらなかったので・・・・。

いつものように、Oracle Database 11g for Linux x86へMacOSXのTerminalからssh接続!

Last login: Sat Oct 20 02:18:51 on console
Welcome to Darwin!
G5Server:˜ discus$ su - oracle
Password:
G5Server:˜ oracle$
G5Server:˜ oracle$ ssh oracle@glasscatfish
oracle@glasscatfish's password:
Last login: Sat Oct 20 02:19:12 2007 from 192.168.1.19
[oracle@glasscatfish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 月 10月 20 14:13:23 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

> conn scott/tiger@lampeye
接続されました。

SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
PL/SQL Release 11.1.0.6.0 - Production
CORE 11.1.0.6.0 Production
TNS for Linux: Version 11.1.0.6.0 - Production
NLSRTL Version 11.1.0.6.0 - Production

SCOTT> set timi on
SCOTT> l
1 xquery
2 for $n in 1 to 100
3 return
4 if ($n mod 15 eq 0) then 'fizzbuzz'
5 else if ($n mod 3 eq 0) then 'fizz'
6 else if ($n mod 5 eq 0) then 'buzz'
7* else $n
SCOTT> /
1
2
fizz
4
buzz
fizz
7
8
fizz
・・・・中略・・・・
fizz
97
98
fizz
buzz

100アイテムが選択されました。

経過: 00:00:00.06
SCOTT>


ついでなので、以前SQLでFizzBuzzしたものと処理時間を比較してみた。
お〜!、SQLでFizzBuzzしたほうが早いな〜!

SCOTT> with
2 t as (
3 select 1 from dual group by cube(1,1,1,1)
4 )
5 select
6 case 0
7 when mod(rownum,15) then 'fizzbuzz'
8 when mod(rownum,3) then 'fizz'
9 when mod(rownum,5) then 'buzz'
10 else to_char(rownum)
11 end as results
12 from
13 t a cross join t b
14 where
15 rownum <= 100;
1
2
fizz
4
buzz
fizz
7
8
・・・・中略・・・・
fizz
97
98
fizz
buzz

100行が選択されました。

経過: 00:00:00.03
SCOTT>


多分、どなたかXQueryでやっているんじゃないかな〜!? ということでググってみたら、ありました、User's Forum For DB2 Japanに。。(^^;;;

いや〜〜〜、目から鱗ですね。User's Forum For DB2 Japanのスレッドにある下記コードは、面白い。(私のコードは読みやすいかもしれないが、ストレート過ぎるかもね。ちょいと捻ったほうが、XQueryのトリッキーな動きも見えてくるというもの。)
以下のコードは、XPath2.0/XQuery1.0では、xs:booleanじゃなくても真理値として扱われる値やシーケンスにフィルタ式を用いているなどなど参考になります。m(_ _)m
(ただ、xs:booleanじゃなくても真理値として扱われるという性質を多用しるぎると難読化傾向はあるかもしれないですね。)

SCOTT> l
1 xquery
2 for $n in 1 to 100
3 return
4 fn:concat(
5 $n[($n mod 3 and $n mod 5)],
6 'fizz'[fn:not($n mod 3)],
7 'buzz'[fn:not($n mod 5)]
8* )
SCOTT> /
1
2
fizz
4
buzz
fizz
7
8
・・・・中略・・・・
97
98
fizz
buzz

100アイテムが選択されました。

経過: 00:00:00.06
SCOTT>


XQueryの条件式を少々書き換えてみた。私が最初に書いたXQueryより条件式の部分が読みにくくなりますよね、やはり。(実行速度に影響がなければ、読みやすい方がいいな。。)

SCOTT> l
1 xquery
2 for $n in 1 to 100
3 return
4 if (fn:not($n mod 15)) then 'fizzbuzz'
5 else if (fn:not($n mod 3)) then 'fizz'
6 else if (fn:not($n mod 5)) then 'buzz'
7* else $n
SCOTT> /
1
2
fizz
4
buzz
fizz
7
8
・・・・中略・・・・
97
98
fizz
buzz

100アイテムが選択されました。

経過: 00:00:00.06
SCOTT>

やはりxs:booleanじゃなくても真理値として扱われるという性質は、間違いやすいところなのでもうちょっと突っ込んで理解しておく必要があるなぁ。いい加減に覚えているとハマりそうな予感。

2007/10/23 追記
Oracle10g R2でもできますよ。

| | コメント (0) | トラックバック (0)

2007年10月16日 (火)

Oracle de XMLDB #3 - Oracle10g XEではどうよ?

OracleのXMLDBを試す簡単な環境は? ということで、Oracle10g R2 Express Editionを試してみた。
だが・・・・・今のところ利用できないようだ。次のリリースに期待。

バックナンバー:
Oracle de XMLDB #1
Oracle de XMLDB #2


以下、前回、Oracle Database 11gを構築したPC(CentOS 5)に、Oracle10g R2 Express Edition for Linux x86を追加インストールして試した記録。
尚、Oracle10g EXへは、同環境へインストール済みOracle Database 11g R1のSQL*Plusから接続した。(MacOSXからssh接続しているため、その方が楽だったので・・・)

G5Server:˜ oracle$ ssh oracle@glasscatfish
oracle@glasscatfish's password:
[oracle@glasscatfish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 火 10月 16 0:04:43 2007

Copyright (c) 1982, 2007, Oracle. All rights reserved.

> conn sys@xe as sysdba
パスワードを入力してください:
接続されました。
SYS>
SYS> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SYS> select comp_name,version,status from dba_registry;

COMP_NAME VERSION STATUS
-------------------------------------------------- ------------------------------ ----------
Oracle Database Catalog Views 10.2.0.1.0 VALID
Oracle Database Packages and Types 10.2.0.1.0 VALID
Oracle Text 10.2.0.1.0 VALID
Oracle XML Database 10.2.0.1.0 VALID

SYS>
SYS> !
[oracle@glasscatfish ˜]$ ll
合計 8
drwxr-xr-x 2 oracle oinstall 4096 10月 14 15:32 Desktop
[oracle@glasscatfish ˜]$ pwd
/home/oracle
[oracle@glasscatfish ˜]$ mkdir scott_xmldir
[oracle@glasscatfish ˜]$ ll
合計 16
drwxr-xr-x 2 oracle oinstall 4096 10月 14 15:32 Desktop
drwxr-xr-x 2 oracle oinstall 4096 10月 14 15:44 scott_xmldir
[oracle@glasscatfish ˜]$ cd scott_xmldir
[oracle@glasscatfish scott_xmldir]$ cat list1.xml
<?xml version="1.0" encoding="UTF-8" ?>
<顧客名簿>
<顧客 id="128">
<住所>
<郵便番号>123-4567</郵便番号>
<都道府県>千葉県</都道府県>
<市町村名>浦安市</市町村名>
<町名番地>舞浜1-2-3</町名番地>
</住所>
<電話 タイプ="会社">03-1234-5678</電話>
<電話 タイプ="自宅">03-5555-6666</電話>
<電話 タイプ="携帯">090-1112-4444</電話>
<ファックス>03-8888-7777</ファックス>
<Eメール>hoge@macdeoracle.jp</Eメール>
</顧客>
<顧客 id="256">
<住所>
<郵便番号>155-5555</郵便番号>
<都道府県>東京都</都道府県>
<市町村名>世田谷区</市町村名>
<町名番地>用賀1-2-3</町名番地>
</住所>
<電話 タイプ="会社">03-7575-7575</電話>
<電話 タイプ="自宅">03-8585-8585</電話>
<電話 タイプ="携帯">090-9191-9191</電話>
<ファックス>03-4141-4141</ファックス>
<Eメール>hoge@discushamburg.jp</Eメール>
</顧客>
<顧客 id="512">
<住所>
<郵便番号>345-4567</郵便番号>
<都道府県>大阪府</都道府県>
<市町村名>中央区</市町村名>
<町名番地>難波2-2-2</町名番地>
</住所>
<電話 タイプ="会社">06-1234-5678</電話>
<電話 タイプ="自宅">06-5555-6666</電話>
<電話 タイプ="携帯">090-0606-0606</電話>
<ファックス>06-8888-7777</ファックス>
<Eメール>hoge@lampeye.jp</Eメール>
</顧客>
</顧客名簿>
[oracle@glasscatfish scott_xmldir]$ exit
exit

SYS>
SYS> create directory scott_xmldir as '/home/oracle/scott_xmldir';

ディレクトリが作成されました。

SYS> grant read on directory scott_xmldir to scott;

権限付与が成功しました。

SYS> grant write on directory scott_xmldir to scott;

権限付与が成功しました。

SYS>

SYS>
SYS>
SYS> conn scott@xe
パスワードを入力してください:
接続されました。
SCOTT>
SCOTT> declare
2 isSuccess boolean;
3 begin
4 isSuccess := dbms_xdb.createfolder('/public/scott');
5 end;
6 /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> l
1 declare
2 r boolean;
3 begin
4 r := dbms_xdb.createresource(
5 '/public/scott/list1.xml',
6 bfilename('SCOTT_XMLDIR','list1.xml'),
7 nls_charset_id('AL32UTF8'));
8* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> xquery
2 let $n := let("/public/scott/list1.xml")
3 return $n
4 /
ERROR:
ORA-19114: XQuery式を解析中にエラーが発生しました:
ORA-06550:行1、列13:
PLS-00201: 識別子SYS.DBMS_XQUERYINTを宣言してください。
ORA-06550:行1、列7:
PL/SQL: Statement ignored


SCOTT>

この日本語のメッセージでググっても、おそらく Oracle10g R2 XE上のXMLDBに関するものはヒットしないだろうということで・・・・

SCOTT> xquery
2 let $n := fn:doc("/public/scott/list1.xml")
3 return $n
4 /
ERROR:
ORA-19114: error during parsing the XQuery expression:
ORA-06550: line 1, column 13:
PLS-00201: identifier 'SYS.DBMS_XQUERYINT' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

英語メッセージに切り替え、英語のメッセージを表示させてからググってみた。
すると、ありましたよ。US OTNに。

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

ということで、Express Editionでは今のところこの機能は動作しないようだ。
次のリリースに期待するしかなさそうですね。



ついに、奥さんがMacBook Pro 15inchを購入、本日届いた! これで、このCentOS5+Oracle11gの環境も初期化して、初代のiMac G5どもども下取だな、そろそろ。
さてさて、LinuxのOracle11g環境を別に作らねば。。

| | コメント (0) | トラックバック (0)

2007年10月15日 (月)

Oracle de XMLDB #2

前回、Oracle XML repositoryへXMLを格納したが、PL/SQLなどのAPIから操作するほか、Enterprise Managerからrepositoryを管理することができる。通常はこちらから管理したほうが楽でしょうね。

バックナンバー:
Oracle de XMLDB #1


以下、CentOS 5に構築したOracle11g の Enerprise Manager Database ControlをSafariから操作している様子。

Em11g_xml_resource1

Em11g_xml_resource2

Em11g_xml_resource3

| | コメント (0) | トラックバック (0)

Oracle de XMLDB #1

前回のエントリでXML Master Professional Database認定試験向けのお勉強用環境をOracle10g/11g環境で作ろうかな。と書いたが早速作ってみた。

Oracle10g R2/Oracle11g R1をインストールすればXMLDBは標準でインストールされているので特に問題になることはないと思う。

ところで、Oracle10g R2からSQL*PlusからXQueryを直接実行できるようになっているのだが、ご存知だろうか?
この例では、Oracle XML RepositoryへXML文書を登録し、SQL*PlusからXQueryを直接発行する環境を作ってみる。

参考:
Oracle XML DB開発者ガイド 10gリリース2(10.2)- 20 Oracle XML DBリポジトリのデータへのアクセス
Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス 10g リリース2(10.2)- 120 DBMS_XDB

まず、今回利用した環境の情報から。
OSは、CentOS4.4(Final) 32bit そう、今年始めに構築した、Oracle10g R2 の Linux RAC環境を利用した。 (Oracle11g R1 EEの環境もあるのだが手順は同じなので Oracle10g R2で構築した例を載せておく。)

[oracle@discus1 ˜]$ uname -svr
Linux 2.6.9-42.EL #1 Sat Aug 12 09:17:58 CDT 2006
[oracle@discus1 ˜]$ cat /etc/redhat-release
CentOS release 4.4 (Final)
[oracle@discus1 ˜]$ srvctl status database -d orcl
インスタンスorcl1はノードdiscus1で実行中です。
インスタンスorcl2はノードdiscus2で実行中です。
[oracle@discus1 ˜]$ srvctl status nodeapps -n discus1
VIPはノードで実行中です: discus1
GSDはノードで実行中です: discus1
リスナーはノードで実行中です: discus1
ONSデーモンはノードで実行中です: discus1
[oracle@discus1 ˜]$ srvctl status nodeapps -n discus2
VIPはノードで実行中です: discus2
GSDはノードで実行中です: discus2
リスナーはノードで実行中です: discus2
ONSデーモンはノードで実行中です: discus2
[oracle@discus1 ˜]$


SYS> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SYS>
SYS> select comp_name,version,status from dba_registry where comp_name like '%XML%';

COMP_NAME VERSION STATUS
-------------------------------------------------- ------------------------------ ----------
Oracle XML Database 10.2.0.1.0 VALID

SYS>


テストに利用するXMLファイル(list1.xml)を $ORACLE_HOME/scott_xmldir以下に作成

[oracle@discus1 scott_xmldir]$ ll
合計 4
-rw-r--r-- 1 oracle dba 2078 10月 13 21:28 list1.xml
[oracle@discus1 scott_xmldir]$ pwd
/u01/app/oracle/scott_xmldir/
[oracle@discus1 scott_xmldir]$ cat list1.xml
<?xml version="1.0" encoding="UTF-8"?>
<顧客名簿>
<顧客 id="128">
<住所>
<郵便番号>123-4567</郵便番号>
<都道府県>千葉県</都道府県>
<市町村名>浦安市</市町村名>
<町名番地>舞浜1-2-3</町名番地>
</住所>
<電話 タイプ="会社">03-1234-5678</電話>
<電話 タイプ="自宅">03-5555-6666</電話>
<電話 タイプ="携帯">090-1112-4444</電話>
<ファックス>03-8888-7777</ファックス>
<Eメール>hoge@macdeoracle.jp</Eメール>
</顧客>
<顧客 id="256">
<住所>
<郵便番号>155-5555</郵便番号>
<都道府県>東京都</都道府県>
<市町村名>世田谷区</市町村名>
<町名番地>用賀1-2-3</町名番地>
</住所>
<電話 タイプ="会社">03-7575-7575</電話>
<電話 タイプ="自宅">03-8585-8585</電話>
<電話 タイプ="携帯">090-9191-9191</電話>
<ファックス>03-4141-4141</ファックス>
<Eメール>hoge@discushamburg.jp</Eメール>
</顧客>
<顧客 id="512">
<住所>
<郵便番号>345-4567</郵便番号>
<都道府県>大阪府</都道府県>
<市町村名>中央区</市町村名>
<町名番地>難波2-2-2</町名番地>
</住所>
<電話 タイプ="会社">06-1234-5678</電話>
<電話 タイプ="自宅">06-5555-6666</電話>
<電話 タイプ="携帯">090-0606-0606</電話>
<ファックス>06-8888-7777</ファックス>
<Eメール>hoge@lampeye.jp</Eメール>
</顧客>
</顧客名簿>
[oracle@discus1 scott_xmldir]$


$ORACLE_HOME/scott_xmldirをdirectoryオブジェクトとして作成。今の所読み込みだけで十分だが、書き込み権限も付与しておく。

SYS> create directory scott_xmldir as '/u01/app/oracle/scott_xmldir/';

ディレクトリが作成されました。

SYS> grant read on directory scott_xmldir to scott;

権限付与が成功しました。

SYS> grant write on directory scott_xmldir to scott;

権限付与が成功しました。

SYS>

SYS>


この例では、XMLファイルをOracle XML repositoryへ登録する。/publicフォルダ以下に scott/xmlフォルダを追加作成後、/public/scott/xml以下へ対象のXMLファイルを登録する。
尚、データベースキャラクタセットは、AL32UTF8であり、登録するXMLファイルのエンコーディングは、UTF-8とした。

まず、/publicフォルダ以下に、scottフォルダを作成する。
SYS> conn scott@orcltest
パスワードを入力してください:
接続されました。

SCOTT> declare
2 r boolean;
3 begin
4 r := dbms_xdb.createfolder('/public/scott');
5 end;
6 /

PL/SQLプロシージャが正常に完了しました。

次に、/public/scottフォルダ以下に、xmlフォルダを作成する。
SCOTT> l
1 declare
2 r boolean;
3 begin
4 r := dbms_xdb.createfolder('/public/scott/xml');
5* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

/public/scott/xmlフォルダ直下へSCOTT_XMLDIRディレクトリオブジェクト以下にあるxmlファイル(list1.xml)を登録し、パスを/public/scott/xml/list1.xmlとする。
SCOTT> l
1 declare
2 r boolean;
3 begin
4 r := dbms_xdb.createresource(
5 '/public/scott/xml/list1.xml',
6 bfilename('SCOTT_XMLDIR','list1.xml'),
7 nls_charset_id('AL32UTF8'));
8* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT>


最後に、確認の意味を含めて、XML repositoryへ登録したxmlをXQueryを利用して、SQL*Plusから直接問い合わせてみる。

SCOTT> set long 4000
SCOTT> l
1 xquery
2 let $d := fn:doc("/public/scott/xml/list1.xml")
3* return $d
SCOTT> /

Result Sequence
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?><顧客名簿><顧客 id="128"><住所><郵便番号>123-4567</郵便番号><都道府県>千葉県</都道府県><市町村
名>浦安市</市町村名><町名番地>舞浜1-2-3</町名番地></住所><電話 タイプ="会社">03-1234-5678</電話><電話 タイプ="自宅">03-5555-6666</電
話><電話 タイプ="携帯">090-1112-4444</電話><ファックス>03-8888-7777</ファックス><Eメール>hoge@macdeoracle.jp</Eメール></顧客><顧客 i
d="256"><住所><郵便番号>155-5555</郵便番号><都道府県>東京都</都道府県><市町村名>世田谷区</市町村名><町名番地>用賀1-2-3</町名番地></
住所><電話 タイプ="会社">03-7575-7575</電話><電話 タイプ="自宅">03-8585-8585</電話><電話 タイプ="携帯">090-9191-9191</電話><ファック
ス>03-4141-4141</ファックス><Eメール>hoge@discushamburg.jp</Eメール></顧客><顧客 id="512"><住所><郵便番号>345-4567</郵便番号><都道府
県>大阪府</都道府県><市町村名>中央区</市町村名><町名番地>難波2-2-2</町名番地></住所><電話 タイプ="会社">06-1234-5678</電話><電話 タ
イプ="自宅">06-5555-6666</電話><電話 タイプ="携帯">090-0606-0606</電話><ファックス>06-8888-7777</ファックス><Eメール>hoge@lampeye.jp
</Eメール></顧客></顧客名簿>



SCOTT>

ここまでできれば、XQuery1.0の実行は、SQL*Plusからダイレクトに行えるようになる。 簡単!。

あとは、いろいろなXQueryを試すのみ! Enjoy!

| | コメント (0) | トラックバック (1)

2007年5月 1日 (火)

DashCode Public Beta - Dashboard de OTN-J #10

前回のつづきです。
ひとまず、今回で、Dashboard de OTN-J widgetは完成です。

● Dashboard de OTN-J widgetでは、OTN-Jのforum全体のfeedだけを読込む widgetにしてあります。

以下のfeed URL固定です。
feed://otn.oracle.co.jp/forum/rss/rssmessages.jspa?categoryID=2

ただし、アプリケーションパッケージに含まれる、attributes.js にfeedのURLが定義されているので直接編集すれば変更することは可能です。(OTN-JのRSS2.0を対象にしています。また、rdfには元のコードが未対応で、atomも一部の情報は表示できません。)
feed urlを変更可能にしたり、atom対応など、OTN-J以外のfeedも表示するなどの version upは行うかもしれませんが、気分次第です。

以下、今回追加したコードの操作確認の模様。赤丸部分でマウスカーソルの形状変化させている。また、裏面では、URLの文字色を赤から黄色に変化させ、クリックすると、当ブログのトップページを開くようにしてある。(ハイパーリンクにすれば簡単なのだが、あえて、そのようにしてある。)

10_1 10_2 10_3
10_4 10_5 10_6

dashboard_de_otn.jsに追加したコード(一部抜粋)。
追加したコードは、マウスカーソル形状を変更するコードや、テキストの色を変更するコード、そして、裏面にあるblogのURLをクリックした際、該当blogをブラウザで開くといった細かい操作を行うためのコードを追加してある。

....中略....

/*****************************************************************
* added by mac de oracle  @2007/4/28                            */

function swapCursor(event)
{
if (event.type == "mouseover") {
document.body.style.cursor = "pointer";
} else if (event.type == "mouseout") {
document.body.style.cursor = "auto";
}
}

function swapTextColor(event)
{
if (event.type == "mouseover") {
event.currentTarget.style.color = "rgb(255, 255, 0)";
} else if (event.type == "mouseout") {
event.currentTarget.style.color = "rgb(255, 0, 0)";
}
}

function addMouseCursorListeners(element, callback)
{
element.addEventListener("mouseover", callback, true);
element.addEventListener("mouseout", callback, true);
}

function openMyBlog()
{
widget.openURL(this.innerText);
}

function addClickListeners(element, callback)
{
element.addEventListener("click", callback, true);
}

/* added by mac de oracle  @2007/4/28 
******************************************************************/

....中略....

function setHandlers()
{
var backOver = new Image();
backOver.src = "Images/backButton_over.png";
var backDown = new Image();
backDown.src = "Images/backButton_down.png";
var forwardOver = new Image();
forwardOver.src = "Images/forwardButton_over.png";
var forwardDown = new Image();
forwardDown.src = "Images/forwardButton_down.png";

var backButton = document.getElementById("backButton");
if (backButton) {
addHilightListeners(backButton, backOver, backDown);

// added by mac de oracle @2007/4/28
addMouseCursorListeners(backButton, swapCursor);
}

var forwardButton = document.getElementById("forwardButton");
if (forwardButton) {
addHilightListeners(forwardButton, forwardOver, forwardDown);

// added by mac de oracle @2007/4/28
addMouseCursorListeners(forwardButton, swapCursor);
}


/****************************************************************
***  added by mac de oracle @2007/4/28                       ***/

var blogURLText = document.getElementById("myBlogURLText");
if (blogURLText) {
addMouseCursorListeners(blogURLText, swapCursor);
addClickListeners(blogURLText, openMyBlog);
addMouseCursorListeners(blogURLText, swapTextColor);
}

var done = document.getElementById("done");
if (done) {
addMouseCursorListeners(done, swapCursor);
}

var refreshButton = document.getElementById("refreshButton");
if (refreshButton) {
addMouseCursorListeners(refreshButton, swapCursor);
}

var info = document.getElementById("info");
if (info) {
addMouseCursorListeners(info, swapCursor);
}

/*** added by mac de oracle @2007/4/28                      
***************************************************************/

}

ざっとこんなところ。。 javascriptのコードをこんなに書いたのも久々。。仕事以外では。。
ただ、javascriptのデバッガを搭載しているDashCodeのおかげで javascriptを久々に書いた
私でもそれほど苦労しなかった。。。便利になってきましたねぇ。ほんとうに!

ということで、ダウンロードはこちらから。dashboard_de_otn.wdgt.zip (216.5K)

参考として、DashCodeのテンプレートに手を加えていないオリジナルのWidgetもダウンロードして比べてみてください。 ダウンロード templete.wdgt.zip (119.7K)

| | コメント (0) | トラックバック (0)

2007年4月25日 (水)

DashCode Public Beta - Dashboard de OTN-J #9

Dashboard de OTN-Jの続きです。
今回は、javascriptを追加して、ひとまず完成まで、と考えていたのだが、大切なことを忘れていたので、まずはそちらから。

何を忘れていたのか? それは、国際化対応。 
DashCodeでも他のMacOSXのアプリケーション同様、国際化対応することが可能だ。

まずは以下のスクリーンショットを見てもらいたい。

7after_front_1


Widgetを起動すると、「Refresh」ボタンや、「Author」ラベル部分が英語のままなのだ。
そこで日本語優先の環境であれば、「Refresh」ボタンは、「リフレッシュ」と表示したり、 「Author」は「投稿者」と表示したい! ということだ。

で、どんなプログラミングが必要なんだ? と気にする必要はなく、以下のように日本語優先環境で表示するテキストを設定だけでいい。 (javaにも同じような仕組みはありますね。。)

Dash9_1

Dash9_2

Dash9_3


Dash9_4 Dash9_5
Dash9_6 Dash9_7

設定が終わったので、DashCode Public Beta上で実行してみると・・・・あれ、英語優先なのね。。。Public Betaなので仕方ない。

Dash9_10

Dashboardにデプロイして確認する.....

Dash9_11 Dash9_12 Dash9_13


日本語表示になっていますね!

Dash9_14 Dash9_15

簡単です!


では今日はここまで。
次回は、本当に、javascriptを追加して、ひとまず完成というところまで。。

| | コメント (0) | トラックバック (0)

DashCode Public Beta - Dashboard de OTN-J #8

Dashboard de OTN-Jの続きです。


今回は、アイコンを追加するといっても作業は超簡単。作成したアイコン用画像をDrag & Dropして、大きさなどをマウスで調整するだけ!

まずは、お手持ちのソフトウェア(gimpや、PhotoShop、FireWorksなどね)でアイコン用画像を作成。今回は大きめだが、256*256の画像を作成した、128*128 で十分だと思うが。。。

Dashboard_de_otn


ナビゲータパネルの「Widget Icon」を選択するとキャンバスには空のアイコンが表示される。そこへ、作成したアイコンをDrag & Drop後、位置や大きさを整える。

8_1_1 8_2


アイコンを設定したところで、Dashboardへデプロイして確認。問題なさそうだ。

8_3 8_4 8_5 8_6


ついでなので、裏面にもアイコン用画像を貼付けることにした。この操作もDrag & Drop後、位置や大きさを調整するのみ。

8_7


外見は、これで完成!。

8_8


次回は、javascriptを少々追加し、ひとまず完成! というところまで。。。

| | コメント (0) | トラックバック (0)

2007年4月24日 (火)

DashCode Public Beta - Dashboard de OTN-J #7

さて、少々間が空いてしまったが、 Dashboard de OTN-Jの続きです。


今回は前回のUIを少々?派手目に変更していくことにする。

ちなみに、DashCode Public betaの変更前のテンプレートは以下のようなものだった。
Before_front Before_back

そして、今回は表裏ともフォントには影を付け、地味だった色を明るくし、グラデーションを付けてみた。
7after_front 7after_back

#サウンドトラック付きなのでファイルは 22MB程度あります。
#BGM付きなので、スピーカーの音量にご注意を!

(再生にはQuickTimeが必要です。)
006


次回は、アイコンを追加する予定。

| | コメント (0) | トラックバック (0)

2007年4月23日 (月)

DashCode Public Beta - Dashboard de OTN-J 番外編 (ちょいと一息)

ちょいと息抜き。。。
Dashboard de OTN-J #4Dashboard de OTN-J #6のQuickTImeムービーのサウンドトラックは、iLife '06のGarageBand3で作っていると書いたが、その様子のスクリーンショット。
GarageBand3って結構面白し、便利ですよ。 簡単なジングルもすぐ作れちゃう。


Garageband3

| | コメント (0) | トラックバック (0)

2007年4月22日 (日)

DashCode Public Beta - Dashboard de OTN-J #6

Dashboard de OTN-Jの続きです。
Widgetの裏側UI変更の模様をQuickTimeムービーで。

●変更前(テンプレートのままのUI)

6_before


●変更後

赤色アンダーラインでMac De OracleのURLを表示しているが、この時点ではテキストを表示しているだけの状態にしてある。将来的には、onmouseoverイベントで文字の色を変えたり、onclickイベントでこのブログをブラウザで開くようにする予定だが。
6_after

#サウンドトラック付きなのでファイルは 25MB程度あります。
#スピーカーの音量にご注意を!

(再生にはQuickTimeが必要です。)
006

| | コメント (0) | トラックバック (0)

2007年4月20日 (金)

DashCode Public Beta - Dashboard de OTN-J #5

前回は、WidgetのフロントUI変更の様子をQuickTimeムービーでお見せしたのだが、どのように変更を加えたのか解りづらいと思うので少々解説しておくことにした。

尚、DashboardのWidgetは、他のMacOSXのアプリケーションと同様にアプリケーションパッケージ(バンドルとか、ファイルパッケージとも呼ばれる)になっている。
Widgetを「右クリック」し、ポップアップメニューの「パッケージ内容を表示」を選択すればパッケージ内容にアクセスできるので、どのようなjavascriptなのか、cssはどうなっているか等、確認することができる。
変更前のパッケージ内容の差分を確認したり、javascript,css等のdiffを取れば、変更部分は容易に確認できると思う。


4_91 4_92

まず、次の2つのWidgetを見比べてもらいたい。(左がオリジナル、右がカスタマイズしたもの。)

4_1_1 4_2

・(A)の部分

オリジナルでは、javascriptコードに問題があるようで、FEEDから<title>要素を取得できず、"Untitled"と表示されている。(DashCode正式版では改善されているでしょうけど。)
カスタマイズ版では、<title>要素を取得できるよう修正し、タイトルは元ネタへのリンクに変更。

・(B)の部分

これはカスタマイズで追加した部分だ。RSS2.0の<author>要素は、OTN-JのRSSでは省略されており、替わりに、拡張された<jf:author>要素が設定されていため、<jf:author>要素値を取り出し、設定すればOK。

・(C)の部分

この部分は本来、エントリの投稿日が表示されるのだが、OTN-JのRSSでは、<item>要素以下の<pubDate>や<dc:date>要素は省略され、替わりに、<jf:createDate>要素が設定されているため、オリジナルでは投稿日が表示されないという状況になっている。
<jf:creationDate>要素値を取り出し設定すればOK.


以下、dashboard_de_otn.js の変更部分から一部抜粋
(DashCodeで新規プロジェクトを作成すると、プロジェクト名称の付いた .jsファイルが作成される。
例えば、dashboard_de_otnというプロジェクト名称を付けた場合、メインの javascriptファイルは、dashboard_de_otn.js というファイルになる。)

尚、OTN-JのRSS2.0向けにカスタマイズしているため、概要部分が長く、スクロールの必要な場合や、ATOMは正しく動作しない場合がりますのでご注意ください。(OTN-JのFEEDでのみ、テストしたため。)

また、オリジナルのコードがRDFには対応していないため、RDFを扱う場合には、さらにコードを追加する必要あり。 
==> XSLTスタイルシートを使って変換後に処理するようにすればもっと楽かも。。
後で調べよう。==>(メモメモ)

変更前(テンプレートを選択すると自動生成?されるjavascriptコード)

// Namespace URLs
var NS_DC = "http://purl.org/dc/elements/1.1/";
var NS_CONTENT = "http://purl.org/rss/1.0/modules/content/";

・・・・・中略・・・・・

function parseRSSFeed(doc)
{
var items = doc.getElementsByTagName("item");
for (var i = 0; i < items.length; i++) {
var thisItem = items[i];

var title = getLocalizedString("Untitled");
var titleElt = getFirstElementByTagName(thisItem, "title", "*");
if (titleElt && titleElt.firstChild) {
title = allData(titleElt);
}

var description;
var descElt = getFirstElementByTagName(thisItem, "encoded", NS_CONTENT);
if (!descElt) {
descElt = getFirstElementByTagName(thisItem, "description", "*");
}
if (descElt && descElt.firstChild) {
description = allData(descElt);
}

var pubDate = getFirstElementByTagName(thisItem, "pubDate", "*");
// If there's a pubDate element, use it
if (pubDate) {
pubDate = new Date(Date.parse(allData(pubDate)));
}
// If not, maybe they're using the Dublin Core date element
if (pubDate == null) {
pubDate = getFirstElementByTagName(thisItem, "date", NS_DC);
if (pubDate) {
var isoDate = allData(pubDate);
pubDate = parseISODate(isoDate);
}
}

if (+attributes.feedType == DFFeedTypeHTML) {
// HTML feed
if (description) {
entries.unshift({ title: title, description: description, date: pubDate });
}
}
else if (+attributes.feedType == DFFeedTypeImage) {
// Photo feed
var image = getFirstImage(description);
if (image) {
entries.unshift({ title: title, image: image, date: pubDate });
}
}
}
}

・・・・・中略・・・・

function setHTMLContent(title, description, date)
{
var content = document.getElementById("content");
if (content) {
clearContent();

if (title != null) {
var titleDiv = document.createElement("div");
titleDiv.setAttribute("id", "entryTitle");
titleDiv.innerHTML = title;
fixLinks(titleDiv);
content.appendChild(titleDiv);
}

if (description != null) {
var descDiv = document.createElement("div");
descDiv.setAttribute("id", "entryDescription");
descDiv.innerHTML = description;
fixLinks(descDiv);
content.appendChild(descDiv);
}

setDateText(date);
}
}

変更後

// Namespace URLs
var NS_DC = "http://purl.org/dc/elements/1.1/";
var NS_CONTENT = "http://purl.org/rss/1.0/modules/content/";
/*****************************
*** for Oracle Technology
*****************************/
var NS_JF = "http://www.jivesoftware.com/xmlns/jiveforums/rss";

・・・・・中略・・・・・

function parseRSSFeed(doc)
{
var items = doc.getElementsByTagName("item");
for (var i = 0; i < items.length; i++) {
var thisItem = items[i];

var title = getLocalizedString("Untitled");
var titleElt = getFirstElementByTagName(thisItem, "title");
if (titleElt && titleElt.firstChild) {
title = allData(titleElt);
}

var description;
var descElt = getFirstElementByTagName(thisItem, "encoded", NS_CONTENT);
if (!descElt) {
descElt = getFirstElementByTagName(thisItem, "description");
}
if (descElt && descElt.firstChild) {
description = allData(descElt);
}

var pubDate = getFirstElementByTagName(thisItem, "pubDate");
// If there's a pubDate element, use it
if (pubDate) {
pubDate = new Date(Date.parse(allData(pubDate)));
}
// If not, maybe they're using the Dublin Core date element
if (pubDate == null) {
pubDate = getFirstElementByTagName(thisItem, "date", NS_DC);
if (pubDate) {
var isoDate = allData(pubDate);
pubDate = parseISODate(isoDate);
}
}

// OTN only
if (pubDate == null) {
pubDate = getFirstElementByTagName(thisItem, "creationDate", NS_JF);
if (pubDate) {
var isoDate = allData(pubDate);
pubDate = parseISODate(isoDate);
}
}

// OTN only
var author;
var authorElt = getFirstElementByTagName(thisItem, "author", NS_JF);
if (authorElt && authorElt.firstChild) {
author = allData(authorElt);
}

var link;
var linkElt = getFirstElementByTagName(thisItem, "link");
if (linkElt && linkElt.firstChild) {
link = allData(linkElt);
}


if (+attributes.feedType == DFFeedTypeHTML) {
// HTML feed
if (description) {
entries.unshift(
{
title: title, description: description,
date: pubDate, author: author, link: link
}
);
}
}
else if (+attributes.feedType == DFFeedTypeImage) {
// Photo feed
var image = getFirstImage(description);
if (image) {
entries.unshift(
{
title: title, image: image,
date: pubDate, author: author, link: link
}
);
}
}
}
}

・・・・・中略・・・・

function setAuthorText(author)
{
var authorText = document.getElementById("authorText");
if (authorText) {
if (author != null) {
authorText.innerText = author;
}
else {
dateText.innerText = getLocalizedString("Author");
}
}
}

function setHTMLContent(title, description, date, author, link)
{
var content = document.getElementById("content");
if (content) {
clearContent();

if (title != null) {
var titleDiv = document.createElement("div");
titleDiv.setAttribute("id", "entryTitle");

var linkElt = document.createElement("a");
linkElt.setAttribute("href", link);
linkElt.innerHTML = title;
titleDiv.appendChild(linkElt);

fixLinks(titleDiv);
content.appendChild(titleDiv);
}

if (description != null) {
var descDiv = document.createElement("div");
descDiv.setAttribute("id", "entryDescription");
descDiv.innerHTML = description;
fixLinks(descDiv);
content.appendChild(descDiv);
}

setDateText(date);
setAuthorText(author);
}
}


最後に、以下の(D)と(E)の部分

「Refresh」ボタンについては、単純に、onClickイベントで、自動生成されたコードに定義されている refreshFeed() を呼んであげればOK。


4_3

「Refresh」ボタンをクリックすれば、日付が表示される部分に Loding... と表示され、最新のFEEDが表示されるようになります。


DashCodeのキャンバス上で、「Refresh」ボタンをクリック->「Inspector」パネル->「Behaviors」タブ-> onclickイベントのHandlersに refreshFeed() を追加してやるだけ!

4_93

では、次回、裏面のカスタマイズにつづく。(一気にアイコン追加と、さらに見栄えを変更する可能性あり。。。)


#押し入れから、ウチの奥さんの本が、、

これ 1999年の本なんですよね。 2000年頃にRubyやってたって聞いていたけど、本気で初期のころだね。
Rubyもやってみたいんだけど。。。奥さん、随分とRubyから遠ざかっているから、奥さんに聞くより、最新の本を買って、遊び始めたほうが早いか。。。。

| | コメント (2) | トラックバック (0)

2007年4月19日 (木)

DashCode Public Beta - Dashboard de OTN-J #4

前回はWidgetのUIを変更したが、それらに対応するJavascriptの変更、追加を行う。

カスタマイズしたWidgetはダウンロードできるようにする予定なので、変更、追加したコードはエントリ上には掲載しないかもしれない。。。(これまた気分次第なので。。)

ということで、その模様を QuickTimeムービーで。
(サウンドトラック付きなのでファイルは 25MB程度あります。)

#スピーカーの音量にご注意を!

(再生にはQuickTimeが必要です。)
004

| | コメント (0) | トラックバック (0)

DashCode Public Beta - Dashboard de OTN-J #3

Dashboard De OTN-Jの3回目。

WidgetのフロントUIの変更は、DashCodeで簡単に行える。(IDEなので、他のIDEを利用したことのある方なら、少々操作すれば、直感的に行えるようになると思いますよ。)

ひとまず以下のようにする事にします。

2_2

まず、「Daily Feed」の配置を右寄せにする。
「Daily Feed」を選択し、「Inspector」パネル->「Text」->「Alignment &: Spacing」で 「Alignment」で右寄せを選択する。

3_1_1
3_2
3_3


次に、 ラベルとして使用するためTextパーツを配置し、"Author:"というラベルを設定する。(日本語にする予定ですが、今はこのまま)
「Library」パネル->「Dashcode Library」プップアップメニュー->「Front」->「Text」を選択する。 Textを選択して、配置したい場所へ Drag & Drop。
配置したテキストは、「左寄せ」で配置するので、「Inspector」パネル->「Text」->「Alignment &: Spacing」で 「Alignment」で左寄せを選択する。
さらに「Inspector」パネル->「Attributeパネル」で、「ID」属性に "author"を設定しておく。

3_5
3_6
3_7


同じ要領で、エントリの投稿者を表示するためのTextパーツを配置し、「Inspector」パネル->「Attributeパネル」で 「ID」属性に"authorText"、「Value」属性の値は動的に設定することになるのだが、配置の確認の為に、"autherText"と設定しておく。

3_8


最後は、最新FEEDを取得するために利用する「Refresh」ボタンを配置する。「Library」パネル->「Dashcode Library」プップアップメニュー->「Front」->「Button」を選択する。「Lozenge Button」を選択し、Widgetの右上にDrag & Dropする。配置したボタンをダブルクリックし、"Refresh"と設定する。最後に、「Inspector」パネル->「Attributeパネル」で、「ID」属性に "refreshButton"というIDを設定しておく。

3_9
3_12
3_13
3_14


これで、ひとまず、フロントUIのカスタマイズは終わり。
フロントUIに関連するjavascriptをカスタマイズにつづく。


3_15

| | コメント (0) | トラックバック (0)

2007年4月18日 (水)

DashCode Public Beta - Dashboard de OTN-J #2

Dashboard De OTN-Jの続きです。

さて、前回テンプレートのままでデプロイしたWidgetをカスタマイズしていくことにする。
第一弾、Widgetのフロントの見栄えを変更したり、表示する情報を増やしていく。

● Before

2_1_1 18_1

● After

2_2

見ての通り、OTN-JのRSS2.0対応FEEDでは、エントリの概要は表示されるものの、投稿日や、エントリのタイトルは表示されていない。

タイトルが表示されていないのは、テンプレートのjavascriptに問題があるためだが、投稿日が表示されていない理由は、OTN-JのRSSには、<pubDate>要素や<dc:date>要素ではなく、独自拡張された<jf:creationDate>要素があるのが理由だ。 UIを変更するついでに纏めて対処する。
変更後のUIでは、タイトルはリンクとして表示し、投稿者、投稿日を表示するほか、「Refresh」ボタンを配置し、最新のFEEDを取得できるようにする。


以下、OTN-JのFEEDより抜粋

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:jf="http://www.jivesoftware.com/xmlns/jiveforums/rss">

<channel>
<title>Oracle Technology Network (OTN) Japan - 掲示板: 投稿メッセージ - OTN</title>
<link>http://otn.oracle.co.jp/forum</link>
<description>Most recent forum messages</description>
<language>ja</language>

<generator>Jive Forums Professional 4.2.4 (www.jivesoftware.com)</generator>
<pubDate>水, 18 4 2007 01:09:17 +0900</pubDate>

<item>
<title>タイトル</title>
<link>http://otn.oracle.co.jp/forum/thread.jspa?messageID=9999&tstart=0#999</link>
<description><![CDATA[ほげほげ]]></description>
<jf:creationDate>火, 17 4 2007 23:44:58 +0900</jf:creationDate>
<jf:modificationDate>火, 17 4 2007 23:44:58 +0900</jf:modificationDate>
<jf:author>asahide</jf:author>
<jf:replyCount>0</jf:replyCount>
</item>

というところで今日は終わり、次回は、UI変更操作を載せる予定。。
(気分次第だが、javascriptの変更記録も載せる。。。。かも。。。)

| | コメント (0) | トラックバック (0)

2007年4月17日 (火)

DashCode Public Beta - Dashboard de OTN-J #1

以前、DashCode Public Betaが、ADCのサイトからダウンロードできるようになっていると書いたが、Leopardのリリースが10月頃まで延期されるということで、しばらくは、正式版DashCodeにお目にかかるのも延びる、ということもあり、少々、DashCode Public Betaで遊んでみる事にした。

で、ネタはどうする? と、しばし考える。。。浮かんだのが、やはり、RSS FEEDを扱うネタ。 
DashCode Public Betaには、FEEDを扱うテンプレートが2種類用意されているので、それら利用することにした。

今回作成するFEED READER widgetの概要は以下。


  1. 対象とするFEEDのサイトは、とりあえず固定。
    Oracle Technology Networkの会議室のFEEDを参照することにする。お約束?!)

  2. DashCode Public Betaで提供されているテンプレートをそのまま、又は、必要に応じて、カスタマイズする。

  3. Widgetに表示するのは、FEEDエントリのタイトルと概要、それに投稿者ぐらいにする。

  4. Widget上に表示されたFEEDエントリのタイトルをクリックすると該当エントリをWebブラウザで開く。

  5. Widgetの裏面に Mac De Oracleへのリンクを配置し、クリックすると Mac De OracleのトップページをWebブラウザで開くようにする。

  6. 最新のFEEDを取得できるよう 「リフレッシュ」ボタンを配置しておく。

できればアイコンまで作る予定。


では、早速、作業開始!

まず、DashCode自体の操作方法に慣れておく必要もあるため、利用するテンプレートを選び、プロジェクトを作成する。その後、テンプレートをカスタマイズしないで、FEED READER Widgetを作成して、自分のDashboardに登録してみたいと思う。(DashCodeでの開発の流れは、これである程度は把握できるのではないかと思うが。。。。)

DashCodeの操作は直感的でいいですね。以下の操作に掛かった時間は、5分もかからなかったと思う。
OSC2007の DashCodeで簡単ウィジェット開発を受講したおかげで、基本的な操作の流れは把握していたこともその理由だが。。。
(尚、DashCodeの解説は、メニューからhelpを選択すると閲覧できるほか、ADCのサイトで参照することもできるので操作方法などの詳細はそちらを参照されたい。)


(1) DashCode Public Betaを起動する。

起動するとテンプレートを選択するダイアログが現れる。RSS FEEDを扱うテンプレートは2種類あるが、今回は、Daily Feedというテンプレートを利用することにした。
1_1


(2) 表示するURLの設定

テンプレートを選択するとキャンバスと呼ばれるPaneにWidgetのひな形が表示される。このひな形の「Drop on RSS Feed URL Here」と表示されているエリアへ、表示したいFEEDのURLをDrag & Dropすれば設定は完了してしまう。

2_1 3_1 4_1 5_1


(3) Widgetの裏面デザイン

最終的には裏面デザインは変更するのだが、今のところテンプレートのままで。
6_1


(4) プロジェクトの保存

基本的な設定はこれだけなので、作成したプロジェクトは名前を付けて保存しておく。
7_2 8_1


(5) Widgetのテスト

作成したWidgetをDashCode上で実行してみる。(DashCode Public Beta版では、実行時のロケールは英語になっているようだ。この点については別途解説する。)

9_1
10
11
12
13 

DashCodeがPublic Beta版ということもあるのだろう。テンプレートをそのまま利用しているだけでは、RSS2.0対応のFEEDの処理には少々問題があるようだ。
例えば、Untitledと表示されている箇所には、各エントリの<title>要素の値が表示されるはず? なのであるが、表示されていない。 (この問題については、カスタマイズ時に改善するつもりだ)

ちなみに、ATOM1.0のURLを設定しても同じく、<title>要素値は表示されない。
尚、Daily Feedと表示されている場所には、該当エントリが投稿された年月日が表示されるのだが、Oracle Techonoloy NetworkフォーラムのFEED(RSS2.0)には、<pubDate>要素や<dc:Date>要素が省略されているため表示されていない。(拡張された要素を参照するようにすれば対応可能なので、widgetをカスタマイズして対応することにする。)


(6) widgetのデプロイ

作成したWidgetをDashboardへデプロイする。デプロイする際、Widget動作の互換性の設定も行える。今回は、MacOSX10.4.3以降で動作するように設定してある。(尚、画面は現在ログインしているユーザのDashboardへWidgetをデプロイする様子。アイコンを設定していないので白のアイコンが表示されている。)

14
15
16
17


(7) Dashboardの表示

デプロイが完了するとDashboardでの表示ができるようになる。表と裏面を表示させた状態のスクリーンショット。テンプレートのままだと、やはり見栄えなどもいまひとつかな。

18


(8) Widgetの管理

Widgetの管理は、「+」アイコンクリック->「ウィジェットの管理...」ボタンをクリックで表示される
テンプレートのままデプロイしてあるので、今回デプロイしたWidgetは白色のアイコンで表示されている。
(このままでは寂しいので、カスタマイズ時には、アイコンを設定することにする。)

19
20
21

今日はここまで。
カスタマイズや、現時点のテンプレートではうまく処理できていない点の修正などは次回以降ということで。。

| | コメント (0) | トラックバック (0)

2007年4月 2日 (月)

Mac De PL/SQL RSS Reader #33 (XSLT編 #5)

さて、前回からのつづき。

●プロシージャのソースです。

HTMLで表示しているため以下のソースをそのままコピー/ペーストするとコンパイルエラーなど不都合が発生することがあるかもしれませんので、ソースを利用される場合は、XSLTスタイルシートも含め、こちらからダウンロードしたソースをお使いください。 source.zip (3.9K)

CREATE OR REPLACE 
PROCEDURE RSS_READER_XSLT
(
i_feedXmlUrl IN VARCHAR2,
i_feedXmlCharset IN VARCHAR2,
i_styleSheetDir IN VARCHAR2,
i_styleSheetName IN VARCHAR2,
DEBUG_ IN BOOLEAN DEFAULT FALSE
)
AS
--===========================================================
rss_reader_xslt.sql : 2007/3/26 - Mac De Oracle
http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/
--============ ===============================================

--============ TYPEs/VARIABLEs ===============================================
XSL_CHARSET_ CONSTANT VARCHAR(30) := 'UTF8';
v_feedXmlUrl VARCHAR2(32767);
v_feedXmlCharset VARCHAR2(30);
v_styleSheetDir VARCHAR2(30);
v_styleSheetName VARCHAR2(100);

myParser DBMS_XMLPARSER.Parser;
v_feedDoc DBMS_XMLDOM.DomDocument;
v_feedSourceClob CLOB;

myProcessor DBMS_XSLPROCESSOR.Processor;
v_xsl DBMS_XSLPROCESSOR.StyleSheet;
v_xslDoc DBMS_XMLDOM.DomDocument;
v_xslSourceClob CLOB;
v_xslDocFragment DBMS_XMLDOM.DomdocumentFragment;
v_transformedDoc DBMS_XMLDOM.DomNode;

v_clobbuffer CLOB;

--========== Internal PROCEDUREs/FUNCTIONs ===================================
PROCEDURE getXMLSource(
i_url IN VARCHAR2,
i_charset IN VARCHAR2 DEFAULT 'UTF-8',
io_sourceClob IN OUT NOCOPY CLOB
)
IS
v_httpReq UTL_HTTP.REQ;
v_httpResp UTL_HTTP.RESP;
v_xmlSource VARCHAR2(1024);
BEGIN
v_httpReq := UTL_HTTP.BEGIN_REQUEST(i_url);
UTL_HTTP.SET_HEADER(
v_httpReq,
'User-Agent',
'Oracle UTL_HTTP/Oracle10g R1;'
);

UTL_HTTP.SET_HEADER(
v_httpReq,
'Content-Type',
'text/xml;charset='||i_charset
);

v_httpResp := UTL_HTTP.GET_RESPONSE(v_httpReq);
DBMS_LOB.CREATETEMPORARY(io_sourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_httpResp, v_xmlSource, true);
v_xmlSource := v_xmlSource || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(
io_sourceClob,
LENGTH(v_xmlSource),
v_xmlSource
);
END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_httpResp);
END;
END getXMLSource;

PROCEDURE drawFeedEntries(
i_buffer IN CLOB
)
IS
chunkSize_ CONSTANT PLS_INTEGER := 10922;
v_numOfChunk PLS_INTEGER;
v_src CLOB;
v_tempStr VARCHAR2(32767);
BEGIN
v_src := i_buffer;
FOR chunk# IN 0..CEIL(DBMS_LOB.GETLENGTH(v_src) / chunkSize_) LOOP
v_tempStr := SUBSTR(i_buffer, (chunk#*chunkSize_)+1, chunkSize_);
HTP.PRN(v_tempStr);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Error Occured : rss_reader_xslt.drawFeedEntries(CLOB).'
);
DBMS_OUTPUT.PUT_LINE(sqlerrm());
RAISE;

END drawFeedEntries;

-- for DEBUG
PROCEDURE pl(text IN CLOB)
IS
BEGIN
IF length(text)> 80 THEN
FOR i IN 1..(trunc(length(text)/80)+1) LOOP
dbms_output.put_line(substr(text,1+ 80*(i-1),80));
END LOOP;
ELSE
dbms_output.put_line(text);
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error occured : pl(VARCHAR2).');
RAISE;
END pl;

--
--
--****************************************************************************
-- Main
--****************************************************************************
BEGIN

v_feedXmlUrl := i_feedXmlUrl;
v_feedXmlCharset := i_feedXmlCharset;
v_styleSheetDir := UPPER(i_styleSheetDir);
v_styleSheetName := i_styleSheetName;

IF v_feedXmlUrl IS NULL THEN
RAISE_APPLICATION_ERROR(-20000, 'FEEDのURLを指定してください。');
END IF;
IF v_styleSheetDir IS NULL THEN
RAISE_APPLICATION_ERROR(
-20001,
'XSLTスタイルシートが保存されているディレクトリを指定してください。'
);
END IF;
IF v_styleSheetName IS NULL THEN
RAISE_APPLICATION_ERROR(-20002, 'XSLTスタイルシート名を指定してください。');
END IF;

-- RSS FEEDの取得する
getXMLSource(
i_url => v_feedXmlUrl,
i_charset => v_feedXmlCharset,
io_sourceClob => v_feedSourceClob
);
myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(myParser, v_feedSourceClob);
v_feedDoc := DBMS_XMLPARSER.GETDOCUMENT(myParser);

-- XSLTスタイルシートを読み込む
v_xslSourceClob := DBMS_XSLPROCESSOR.READ2CLOB(
v_styleSheetDir,
v_styleSheetName,
NLS_CHARSET_ID(XSL_CHARSET_)
);
DBMS_XMLPARSER.PARSECLOB(myParser, v_xslSourceClob);
v_xslDoc := DBMS_XMLPARSER.GETDOCUMENT(myParser);
v_xsl := DBMS_XSLPROCESSOR.NEWSTYLESHEET(v_xslDoc, NULL);

-- DOMにXSLTスタイルシートを適用する
myProcessor := DBMS_XSLPROCESSOR.NEWPROCESSOR();
v_xslDocFragment := DBMS_XSLPROCESSOR.PROCESSXSL(
myProcessor,
v_xsl,
v_feedDoc
);
v_transformedDoc := DBMS_XMLDOM.MAKENODE(v_xslDocFragment);
DBMS_LOB.CREATETEMPORARY(v_clobbuffer, FALSE);
DBMS_XMLDOM.WRITETOCLOB(v_transformedDoc, v_clobbuffer);

-- 変換後のHTMLを出力する
IF DEBUG_ THEN
pl(v_clobbuffer);
ELSE
drawFeedEntries(v_clobbuffer);
END IF;

DBMS_LOB.FREETEMPORARY(v_feedSourceClob);
DBMS_LOB.FREETEMPORARY(v_xslSourceClob);
DBMS_LOB.FREETEMPORARY(v_clobbuffer);
DBMS_XSLPROCESSOR.FREESTYLESHEET(v_xsl);
DBMS_XMLDOM.FREEDOCUMENT(v_feedDoc);
DBMS_XMLDOM.FREEDOCUMENT(v_xslDoc);
DBMS_XMLPARSER.FREEPARSER(myParser);
DBMS_XSLPROCESSOR.FREEPROCESSOR(myProcessor);

EXCEPTION
WHEN OTHERS THEN
IF v_feedSourceClob IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_feedSourceClob);
END IF;
IF v_xslSourceClob IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_xslSourceClob);
END IF;
IF v_clobbuffer IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_clobbuffer);
END IF;
DBMS_XSLPROCESSOR.FREESTYLESHEET(v_xsl);
DBMS_XMLDOM.FREEDOCUMENT(v_feedDoc);
DBMS_XMLDOM.FREEDOCUMENT(v_xslDoc);
DBMS_XMLPARSER.FREEPARSER(myParser);
DBMS_XSLPROCESSOR.FREEPROCESSOR(myProcessor);

IF DEBUG_ THEN
DBMS_OUTPUT.PUT_LINE('RSS Reader error:'||SQLERRM());
ELSE
HTP.TABLEOPEN();
HTP.TABLEROWOPEN();
HTP.TABLEHEADER('RSS Reader error:'||SQLERRM());
HTP.TABLEROWCLOSE();
HTP.TABLECLOSE();
END IF;
END RSS_READER_XSLT;
/


このサンプルは OTN-Jの CodeTipsでも公開しています。

(1/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2135
(2/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2137
(3/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2138

| | コメント (0) | トラックバック (0)

2007年4月 1日 (日)

Mac De PL/SQL RSS Reader #32 (XSLT編 #4)

つづきです。

XSLTスタイルシートに関して細かく解説するつもりはありませんが、少しだけ解説しておくと。

RSS 0.91/RSS 0.92/ RDF(RSS)1.0ATOM 0.3 / ATOM 1.0の FEEDからタイトルと元ネタへのリンク、各エントリ毎の要約とリンク、そして、存在してれば、[エントリの作成日]を抜き出してHTMLへ変換している。
尚、OTN-JRSS2.0で配信されているが 各エントリには、<pubDate>要素や、<dc:date>要素は存在せず、拡張された<jf:creationDate>要素に作成日を持っているようなので、<jf:creationDate>要素を処理している。

XSLTについては、@ITの記事などや、検索すれば沢山ヒットするので理解できる範囲かと。。。
(難しいことはやってないですから。)
http://www.atmarkit.co.jp/fxml/tanpatsu/xslt/xslt04.html
http://www.atmarkit.co.jp/fxml/tanpatsu/xslt/xslt10.html

尚、DBMS_XSLPROCESSORパッケージなどは、
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19245-01/d_xslpro.htmを参照のこと。

簡単な解説はこれぐらいにして、以下、XSLTスタイルシートのソース。
#1時間くらいで作ったものなので、バグが無いとは言えません。あしからず。
#ちなみに、私が読んでいるFEEDでは特に問題は発生していません。

但し、こんな問題もあり2月に入ってからDTDが開けないエラーが発生している。大抵、他の形式でも配布しているからRSS0.91使わなきゃいいだけかも。。

尚、今回作成したXSLTスタイルシートとPL/SQLのソースコードは、こちらからダウンロードできます。 source.zip (3.9K)

<?xml version="1.0" encoding="utf-8"?>
<!-- ===================================================================
rss2html.xsl : 2007/3/26 - Mac De Oracle
http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/
==================================================================== -->
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rss10="http://purl.org/rss/1.0/"
xmlns:atom03="http://purl.org/atom/ns#"
xmlns:atom10="http://www.w3.org/2005/Atom"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:jf="http://www.jivesoftware.com/xmlns/jiveforums/rss"
>


<xsl:output method="html" encoding="utf-8" />
<xsl:template match="/">
<table border="0" cellpadding="0" cellspacing="2">
<tr>
<th>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:apply-templates select="//rdf:RDF/rss10:channel/rss10:link"/>
<xsl:apply-templates select="//atom03:feed/atom03:link/@href"/>
<xsl:apply-templates select="//atom10:feed/atom10:link/@href"/>
<xsl:apply-templates select="//rss/channel/link"/>
</xsl:attribute>
<xsl:apply-templates select="//rdf:RDF/rss10:channel/rss10:title"/>
<xsl:apply-templates select="//atom03:feed/atom03:title"/>
<xsl:apply-templates select="//atom10:feed/atom10:title"/>
<xsl:apply-templates select="//rss/channel/title"/>
</xsl:element>
</th>
</tr>
<xsl:apply-templates select="//rdf:RDF/rss10:item" mode="normal"/>
<xsl:apply-templates select="//atom03:feed/atom03:entry" mode="normal"/>
<xsl:apply-templates select="//atom10:feed/atom10:entry" mode="normal"/>
<xsl:apply-templates select="//rss/channel/item" mode="normal"/>
</table>
</xsl:template>


<!-- RDF/RSS1.0 template -->
<xsl:template match="rss10:item" mode="normal">
<tr>
<td valign="top">
<xsl:element name="a">
<xsl:attribute name="href"><xsl:value-of select="rss10:link"/></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="rss10:link"/></xsl:attribute>
<xsl:attribute name="style">color:#FF0000</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:value-of select="concat(rss10:title, ' - 続きを読む...')" />
</xsl:element>
<xsl:choose>
<xsl:when test="dc:date">
<xsl:value-of select="concat(' - ', substring-before(dc:date,'T'))"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</td>
</tr>
</xsl:template>

<xsl:template match="//rdf:RDF/rss10:channel/rss10:title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="//rdf:RDF/rss10:channel/rss10:link">
<xsl:value-of select="."/>
</xsl:template>


<!-- ATOM 1.0 template -->
<xsl:template match="//atom10:feed/atom10:entry" mode="normal">
<tr>
<td valign="top">
<xsl:element name="a">
<xsl:attribute name="href"><xsl:value-of select="atom10:link/@href"/></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="atom10:summary"/></xsl:attribute>
<xsl:attribute name="style">color:#FF0000</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:value-of select="concat(atom10:title,' - 続きを読む...')"/>
</xsl:element>
<xsl:choose>
<xsl:when test="atom10:published">
<xsl:value-of select="concat(' - ',substring-before(atom10:published,'T'))"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</td>
</tr>
</xsl:template>

<xsl:template match="//atom10:feed/atom10:title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="//atom10:feed/atom10:link/@href">
<xsl:if test="../@rel = 'alternate'">
<xsl:if test="../@type = 'text/html'">
<xsl:value-of select="."/>
</xsl:if>
</xsl:if>
</xsl:template>


<!-- ATOM 0.3 template -->
<xsl:template match="//atom03:feed/atom03:entry" mode="normal">
<tr>
<td valign="top">
<xsl:element name="a">
<xsl:attribute name="href"><xsl:value-of select="atom03:link/@href"/></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="atom03:summary"/></xsl:attribute>
<xsl:attribute name="style">color:#FF0000</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:value-of select="concat(atom03:title, ' - 続きを読む...')"/>
</xsl:element>
<xsl:choose>
<xsl:when test="atom03:issued">
<xsl:value-of select="concat(' - ', substring-before(atom03:issued, 'T'))"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</td>
</tr>
</xsl:template>

<xsl:template match="//atom03:feed/atom03:title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="//atom03:feed/atom03:link/@href">
<xsl:if test="../@rel = 'alternate'">
<xsl:if test="../@type = 'text/html'">
<xsl:value-of select="."/>
</xsl:if>
</xsl:if>
</xsl:template>


<!-- RSS 0.91/0.92/2.0 template -->
<xsl:template match="//rss/channel/item" mode="normal">
<tr>
<td valign="top">
<xsl:element name="a">
<xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="link"/></xsl:attribute>
<xsl:attribute name="style">color:#FF0000</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:value-of select="concat(title, ' - 続きを読む...')"/>
</xsl:element>
<xsl:choose>
<xsl:when test="pubDate">
<xsl:value-of
select="concat(
' - ',
substring(
substring-before(jf:creationDate, ':'),
1,
string-length(substring-before(jf:creationDate, ':'))-3
)
)"
/>
</xsl:when>
<xsl:when test="dc:date">
<xsl:value-of select="concat(' - ', substring-before(dc:date, 'T'))"/>
</xsl:when>
<xsl:otherwise>
<!-- for OTN rss -->
<xsl:if test="jf:creationDate">
<xsl:value-of
select="concat(
' - ',
substring(
substring-before(jf:creationDate, ':'),
1,
string-length(substring-before(jf:creationDate, ':'))-3
)
)"
/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:template>

<xsl:template match="//rss/channel/title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="//rss/channel/link">
<xsl:value-of select="."/>
</xsl:template>

</xsl:stylesheet>

長くなるので、PL/SQLのソースは次回。




このサンプルは OTN-Jの CodeTipsでも公開しています。

(1/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2135
(2/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2137
(3/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2138

| | コメント (0) | トラックバック (0)

2007年3月30日 (金)

Mac De PL/SQL RSS Reader #31 (XSLT編 #3)

前回前々回と、いきなりデバッグの後半部分とApex3.0 での動作確認を載せていたので、今回は、少しだけ解説を。

XSLTスタイルシートは、Oracleのディレクトリオブジェクトから読み込んだと書いたが、まずはその点から解説しておこう。
ディレクトリオブジェクトを作成し、Apex3.0でアプリケーションの格納に利用する「作業領域」に割り当てられたスキーマへディレクトリオブジェクトの読み込み権限を付与しておく。

SYS> create directory plsql_de_xslt as '/Volumes/Discus/4oracle/oracle/plsql_de_xslt/';

ディレクトリが作成されました。

SYS> grant read on directory plsql_de_xslt to aquarium;

権限付与が成功しました。

尚、「作業領域」に割り当てられているスキーマの確認方法は、
Application Express管理サービスにログイン->「作業領域の管理」->「作業領域とスキーマの割当の管理」

31 32
33 34
上記のスクリーンショットを見れば一目瞭然だが、作業領域:aquariumにaquariumスキーマが割り当てられていることが確認できる。


ディレクトリオブジェクトの準備が済んだら、事前に作成しておいたXSLTスタイルシート(文字エンコーディングは、UTF-8とした)をディレクトリオブジェクトに対応付けされたディレクトリへ配置する。(以下は配置後の状態)

discus:˜/plsql_de_xslt oracle$ pwd
/Volumes/Discus/4oracle/oracle/plsql_de_xslt
discus:˜/plsql_de_xslt oracle$ ls
RssToXhtml.xsl
discus:˜/plsql_de_xslt oracle$

PL/SQLでは、DBMS_XSLPROCESSOR.READ2CLOB()ファンクションを使って読み込むことができる。


例えば、
●ディレクトリオブジェクト名:"PLSQL_DE_XSLT"
●XSLTスタイルシート名:"RssToXhtml.xsl"
●文字エンコーディング: "UTF-8"

である場合は以下のように指定する。
注意する点は、キャラクタセットIDだろう。NLS_CHARSET_ID関数を利用しキャラクタセット名からキャラクタセットIDに変換する必要がある。また、指定するキャラクタセット名は、Oracle Database グローバリゼーション・サポート・ガイドに記載されている名称を指定する。 この例では、UTF8

==> 私もハマりました。つい、"UTF-8"って指定してしまって。。。(^^;;;; しばらく悩みました。。はい。

  tempClob :=  DBMS_XSLPROCESSOR.READ2CLOB(
'PLSQL_DE_XSLT',
'RssToXhtml.xsl',
NLS_CHARSET_ID('UTF8')
);

また、以前にも書いたが、 DBMS_XMLPARSER.PARSER(url)を使ってRSS FEEDをパースできればいいのだが、今のところ、マルチバイトを利用している場合には文字化けの影響があるので、面倒だがUTL_HTTPパッケージを利用し自前でCLOBに取込んでからパースするようにしている。 

| | コメント (0) | トラックバック (0)

2007年3月29日 (木)

Mac De PL/SQL RSS Reader #30 (XSLT編 #2)

さて、SQL Developerでの確認も終わり、さっそく、Apex3.0で試してみた。

いつものように、「Hide and Show Region」を選択し、RSS 0.91/0.92/1.0/2.0 ATOM 0.3/1.0で配信されているFEEDを読み込むよう設定した。

Ap1_1 Ap2 


アプリケーションを実行した結果は以下。思い通りに変換されている。(XSLTスタイルシートを利用しているので、見栄えを変更する場合はXSLTスタイルシートを修正するだけ。。)

Ap3 Ap4

まあ、なんとか、以前のものとおなじような見栄えにはなりますね。(XSLT2.0ならもっといろいろとできるでしょうけども)
以下マニュアル引用


PL/SQL XSLT Processor for XMLType: Features

PL/SQL XSLT Processor for XMLType (DBMS_XSLPROCESSOR) is the Oracle XML DB implementation of the XSL processor. This follows the W3C XSLT final recommendation (REC-xslt-19991116).

W3C XSL Transformations(XSLT) バージョン 1.0の和訳はこちら。
http://www.infoteria.com/jp/contents/xml-data/REC-xslt-19991116-jpn.htm

次回へつづく。




植木等さんの名作といえば、無責任シリーズかもしれません。(今見ても、笑えますもん)
ただ、私などはリアルタイムで無責任シリーズを見た世代ではないので、「オヨビでない奴!」というドラマの印象が強烈かもしれない。
所ジョージと高橋良明が植木等にからみ、植木等の3乗くらいの面白さのあったドラマに仕上がっていたと思います。
ところで、所ジョージに植木等のまねをやらせたら似てるよ、きっと。。。

植木等さんのご冥福を心よりお祈りいたします。

| | コメント (0) | トラックバック (0)

Mac De PL/SQL RSS Reader #29 (XSLT編#1)

ノドが痛いと思っていたら、熱。インフルエンザではないが、風邪には違いない。(油断禁物ですね。。)1日休んだら、回復しましたけど、本調子に戻っていないので今日はおとなしくして明日は完全復活する予定。(週末は花見もしないとならんし。。な)


さて、PL/SQLでRSS Readerを作ってきたが、XSLTスタイルシートを利用した場合はどうなるか?
ということで、以前のプロシージャをベースに、XSLT版に書き換えてみることにする。

利環境は前回からの続きなので変更はないのだが、念のために、データベース、Web Toolkit、そして、Apexのバージョンを載せておく。

SYS> select version from v$instance;

VERSION
-----------------
10.1.0.3.0


SYS> select owa_util.get_version from dual;

GET_VERSION
--------------------------------------------------------
10.1.2.0.6

SYS> select flows_030000.wwv_flows_release from dual;

WWV_FLOWS_RELEASE
--------------------------------------------------------
3.0.0.00.20

SYS>

尚、開発には、 Oracle SQL Developer 1.1.2.25 Build Main 25.79 を使用した。

SQL Developerでは、OWAの出力もできるようなので試したかったということもあったのだが。。。

試してみるとOWAが書き出す量が多いとエラーになるようだ、具体的にどの程度ということまでは確認していないのだが。。HTP.PRNで4000バイト以上は書き出している。
但し、エラー時にもHTP.PRINTでエラー内容を出力しているのだが、こちらは、画面のスナップショットからも判るように問題なく表示されている
(前述の問題は、dbms_outputパッケージで代用できるので、特に困るということもないので深入りしないでスルー。(^^;;;)


X1 X2

前回までとは異なり、PL/SQL内部でDOMをトラバースしたりすることはせず、XSLTスタイルシートを利用してRSS/RDF/ATOMをHTMLに変換する。
変換後のHTMLには、FEEDのタイトル及びリンク、各記事の要約とリンク、それに記事の作成日があれば表示することにした。
尚、記事の作成日については、該当要素値から日付(RFC3339形式)部分を表示することにした。(RFC882形式の場合は、曜日も含める)
また、XSLスタイルシートの読み込み方法は幾つかあるが、今回はディレクトリオブジェクト以下にあるスタイルシートを読み込むことにした。。

XSLTスタイルシートで、xsl:choose要素や、xsl:if要素。xsl:variable要素なんて多用してしまうと、もの凄く読みにくいJSPのようになってしまいそうな気がする。。。
ところで、しっかりと内容を確認していないのだが、XML Master professional Database を取るべきか、Applicationを取るべきか悩みなすね。。


DBMS_OUTPU.PUT_LINEを利用してデバック変換後のHTMLを表示しているところ。

X3 X4
X5 X6


適当に作ったXSLTスタイルシートもなんとか思い通りのもにに仕上がったので、Apex3.0でお試し。。

次回へつづく。

| | コメント (0) | トラックバック (0)

2007年2月22日 (木)

Mac De PL/SQL RSS Reader #28 - メモ

OTN-JフォーラムのFEEDはUS OTNと同じく、RSS2.0となっているようだ。(下記XMLソース抜粋参照のこと。)


item要素にはネームスペースで拡張された、jf:creationDate要素や、jf:author要素は存在するが、author要素や、pubDate要素が存在しない。

そのため、FirefoxやSarafi、Google RSS readerなどでは、投稿者や日時が表示されない。
US OTNの場合と同じなのだが、投稿日があると便利でしょと思うのは私だけ?

Safariでは投稿日関連する要素が存在しない場合には、FEEDを取込んだ日時を表示してくれるので、多少は助かる。
Safari


Firefox2では、日時表示は全くない(pubDate要素がないので当然だが。。)
Firefox2


Google ReaderでもFirefox2に同じ。
Googlerssreader

リニューアルついでなので、author要素や、pubDate要素くらい追加してもらえるといいのだが・・・OTN-Jさん。。。と思いつつ。。





ということで、Apex2.2に組み込んだPL/SQLのRSS FEED Readerのコードを変更するのもいいかと思い始めた。


例えば、OTNのRSS2.0 FEEDのように、item要素には、pubDate要素が含まれず、名前空間で拡張されたjf:creationDate要素がある場合、
RSS FEED Reader側で、どのネームスペースのどの要素を使うかなんて設定できるようにすれば、便利かな〜〜と思った次第。。
(あと、jf:createDate要素値は、rfc822形式のようだが、曜日が日本語表記なので、英語表記へ変換する必要あり。(現行のコードのままだと例外が飛ぶはずなので、それも含め、コードの見直しを考えてみますか。。。

<rss version="2.0" xmlns:jf="http://www.jivesoftware.com/xmlns/jiveforums/rss">
<channel>
・・・・中略・・・・
<item>
<title>Re: 追記: 名前空間を使用したXqueryの使用方法に関して</title>
<link>http://otn.oracle.co.jp/forum/thread.jspa?messageID=35001142&tstart=0#35001142</link>

<description><![CDATA[名前空間のURLが間違っているのでは? (.xsd が抜けているとか。)]]></description>

<jf:creationDate>金, 09 2 2007 18:55:56 +0900</jf:creationDate>
<jf:modificationDate>金, 09 2 2007 18:55:56 +0900</jf:modificationDate>
<jf:author>xxxxxx</jf:author>
<jf:replyCount>0</jf:replyCount>
</item>
・・・・以下略・・・・

| | コメント (2) | トラックバック (0)

2007年2月21日 (水)

Mac De PL/SQL RSS Reader番外編-OTN-J Forum RSS FEED配信開始記念?!

2月1日からOTN-JのForumがリニューアルされ、US OTNのForumのように新規投稿がRSS FEEDで配信されるようになった。(やっとと言った感じ。US OTNに遅れること。。。?年という感じなので待ちくたびれていたところだった。。。)

さっそく、Safariで、会議室のFEEDをブックマークしてみるとUS OTNのように新着記事が取込まれている。。
クリックして各記事を眺めてみても問題なさそうだなぁ。
と思い、折角だから、Apex2.2に組み込んだ RSS READERで試しはじめたころから、リニューアルしたフォーラムの問題に気づき始める。。。。

まず、以前にも試していた、PL/SQLでRSS FEED ReaderをApex2.2に組み込み、OTN-JのFEEDを取込むと、、、なんと、パースエラー!
ん? このエラーは、以前にも見たような気がする。。が、ちゃんとUTL_HTTPパッケージを利用し、UTF-8で取込むことで回避したはずだ。。おかしい。。Safariでは文字化けなど発生していない!!

Xml_parse_error_plsql


そこで、MacOSX版 Firefox2でプレビューモードにしてOTN-JのFEEDを取込んでみると。。。
お〜〜〜。見事にXMLパースエラー!!

Xml_parse_error


ところが、再度行うと、今度は、文字化け!
さらに不思議なことに、、、ブックマークしたFEEDのエントリは文字化けしていないではないか??(なんだこりゃ!)

Xml_no_parse_error_but


その後、何度か試していると、上手く取込める場合、XMLパースエラーになる場合、パースエラーにはならないが文字化けする状態がランダムに発生することが分かった。
UTF-8以外の文字コードで送信されてしまう状態がランダムに発生しているようにみえた。(・・・経路が違うのかもしれない。例えばキャッシュを経由した場合とそれ以外のように、。。と勝ってに想像したりしている。)

そして、OTN-Jがリニューアルされてから、9日目のこと、Firefox2上でのFeedの文字化けも収まった?模様?で、文字化けやXMLパースエラーにはお目にかからなくなった。


ということで、再度、Apex2.2に組み込んだPL/SQLで作成したFEED READERで、OTN-JのXMLの部屋のFEEDを取込んでみた。


(再生にはQuickTimeが必要です。)

apex2.2

なんとか、読めるようになりましたね。。。。。OTN-J様。ご苦労さまです。m(_ _)m。

| | コメント (0) | トラックバック (0)

2006年12月 3日 (日)

Mac De Oracle - XSLTProcessor Error

先月あたりだったと思うが、OTN USのSoftware DownloadのFEEDが変だ。Safariだと、OTN US上のページでもエラーになるし、FEEDの表示もおかしい。

以下、Safari2.0.4(419.3)でブラウズした様子。
Xsltprocessor_safari_1



試しに、FIreFox 2.0で見てみると、、、、

Xlstprocessor_firefox

正しく表示できる。ちなみに、FEEDを表示しても正しく表示されている。
いずれ修正してくれるだろうけど。。。

尚、FireFoxには、以下のテーマを適用しているので、外見は、Safariそっくり!。
Grapple_firsfox_thema

| | コメント (0) | トラックバック (0)

2006年11月20日 (月)

Mac De PL/SQL RSS Reader #27 (+)

Mac De PL/SQL RSS Reader #27で公開したコードがOTN-JapanのCocd Tipsで公開されました。

尚、記事が大きく3分割してあります。

Code Tips PL/SQLで RSS Feed Reader (1/3)
Code Tips PL/SQLで RSS Feed Reader (2/3)
Code Tips PL/SQLで RSS Feed Reader (3/3)

尚、OTN-JapanのCode Tipsを見るには、OTN-Japanへのユーザ登録が必要です。

※オラクルライセンスセンターのアフィリエイトも追加しました。



いいねぇ、Saigenji

聞いている曲:Saigenji - SAIGENJI - 孤動 saigenji - SAIGENJI - 孤動

| | コメント (0) | トラックバック (0)

2006年11月 4日 (土)

Mac De PL/SQL RSS Reader #27

RSS Readerの続き。

週末、美味しいワインのつまみのレシピを多摩美の芸術祭りに模擬店を出しているmiwaさん教えてもらいニッコリ!!

さて、APEX2.2に組み込んだPL/SQLで作成したRSS Readerストアドプロシージャのソースを公開。
ひとまず、これで、RSS Readerネタは終了。
Oracle Portalのデータベースポートレット向けにするとか、XSLT版というのも面白いと思っているが、それらはまた、気が向いたときにでも。。 

以下は、APEXに組み込んだデモをQiuckTime Movieにしたもの。(再生にはQuickTimeが必要です。)


Apex_de_rss_reader_demo4


そして、RSS Readerストアドプロシージャのソースは以下。
ただし、ブラウザに表示するためソースコードの一部の文字を
文字参照に置換してある。( < > " ¥ など) 

オリジナルのスクリプトrss_reader.sqlはこちら。(エンコーディングは、shift_jis。)

(RFC822や、RFC3339のDate / Time関連関数は、ストアドプロシージャの内部関数化してある。これらをパッケージ化するほうが分かりやすくなるかもしれないが、それらの内部関数を単独で利用することもないのでストアドプロシージャの内部関数としてある。)

CREATE OR REPLACE PROCEDURE RSS_READER
(
i_feedXmlUrl IN VARCHAR2
)
AS
--============ TYPEs/VARIABLEs ===============================================
C_RSS CONSTANT VARCHAR2(7) := 'rss';
C_RDF CONSTANT VARCHAR2(7) := 'rdf:RDF';
C_ATOM CONSTANT VARCHAR2(7) := 'feed';
-- C_ATTR_NAME_VERSION CONSTANT VARCHAR2(7) := 'version';

v_feedXmlUrl VARCHAR2(32767);

TYPE FeedEntryType IS RECORD
(
title VARCHAR2(2000),
link VARCHAR2(200),
published TIMESTAMP WITH LOCAL TIME ZONE
);
v_feedEntryList DBMS_XMLDOM.DomNodeList;
v_feedTitle VARCHAR2(2000);
v_feedUrl VARCHAR2(200);

v_myParser DBMS_XMLPARSER.Parser;
v_feedDoc DBMS_XMLDOM.DomDocument;

v_rootElementTagName VARCHAR2(7);
-- v_feedVersion VARCHAR2(40);
v_feedSourceClob CLOB;
v_nsAttrXmlNameSpaces VARCHAR2(32767);

--========== Internal PROCEDUREs/FUNCTIONs ===================================
FUNCTION RFC3339_DateStrToTimeStampLTZ(
i_dateTimeString IN VARCHAR2
)
RETURN TIMESTAMP WITH LOCAL TIME ZONE
AS
C_NLS_DATE_LANGUAGE CONSTANT VARCHAR2(40) := 'NLS_DATE_LANGUAGE=AMERICAN';
v_tempTimeStampTz TIMESTAMP WITH LOCAL TIME ZONE := NULL;
v_dateTimeString VARCHAR2(50) := NULL;
v_timeStampTzFormat VARCHAR2(40) := NULL;
BEGIN
v_dateTimeString := REGEXP_REPLACE(
REGEXP_REPLACE(
UPPER(i_dateTimeString),
'T', NULL, 1, 1
),
'Z$', 'UTC'
);

IF v_dateTimeString IS NULL THEN
RETURN NULL;
END IF;


v_timeStampTzFormat := 'RRRR-MM-DD';

IF LENGTH(v_dateTimeString) >= 10 THEN

IF REGEXP_INSTR(v_dateTimeString , '([0-9]{2}:){2}[0-9]{2}¥.?') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI:SSXFF';
END IF;

IF REGEXP_INSTR(v_dateTimeString, '(¥+|¥-)[0-9]{2}:[0-9]{2}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZH:TZM';
ELSIF REGEXP_INSTR(v_dateTimeString, 'UTC$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZR';
END IF;
END IF;

v_tempTimeStampTz := TO_TIMESTAMP_TZ(
v_dateTimeString,
v_timeStampTzFormat,
c_nls_date_language
);

RETURN v_tempTimeStampTz;

EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(
-20002,
'RFC3339_DateStrToTimeStampLTZ():' || SQLERRM()
);
RETURN NULL;
END RFC3339_DateStrToTimeStampLTZ;


FUNCTION RFC822_DateStrToTimeStampLTZ
(
i_dateTimeString IN VARCHAR2
)
RETURN TIMESTAMP WITH LOCAL TIME ZONE
AS
C_NLS_DATE_LANGUAGE CONSTANT VARCHAR2(40) := 'NLS_DATE_LANGUAGE=AMERICAN';
v_tempTimeStampTz TIMESTAMP WITH LOCAL TIME ZONE := NULL;
v_dateTimeString VARCHAR2(50) := NULL;
v_timeStampTzFormat VARCHAR2(40) := NULL;
BEGIN
v_dateTimeString := UPPER(i_dateTimeString);
IF v_dateTimeString IS NULL THEN
RETURN NULL;
END IF;

IF REGEXP_INSTR(v_dateTimeString, '^[A-Z]{3}¥, ') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'DY, ';
END IF;

v_timeStampTzFormat := v_timeStampTzFormat || 'DD MON RRRR';
IF REGEXP_INSTR(v_dateTimeString, '[0-9]{2}:[0-9]{2}:[0-9]{2}') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI:SS ';
ELSIF REGEXP_INSTR(v_dateTimeString, '[0-9]{2}:[0-9]{2}') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI ';
END IF;

IF REGEXP_INSTR(v_dateTimeString, ' (¥+|¥-)[0-9]{4}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZHTZM';
ELSIF REGEXP_INSTR(v_dateTimeString, ':[0-9]{2}$') = 0
AND REGEXP_INSTR(v_dateTImeString, '[0-9]{2} [A-Z]{3} [0-9]{2,4}$') = 0
AND REGEXP_INSTR(v_dateTImeString, ' [A-Z]{1,3}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZR';
END IF;

v_tempTimeStampTz := TO_TIMESTAMP_TZ(
v_dateTimeString,
v_timeStampTzFormat,
c_nls_date_language
);

RETURN v_tempTimeStampTz;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(
-20001,
'RFC822_DateStrToTimeStampLTZ():' || SQLERRM()
);
RETURN NULL;
END RFC822_DateStrToTimeStampLTZ;


PROCEDURE getFeedSource(
i_feedXmlUrl IN VARCHAR2,
i_feedXmlCharset IN VARCHAR2 DEFAULT 'UTF-8',
io_feedSourceClob IN OUT NOCOPY CLOB
)
IS
v_httpReq UTL_HTTP.REQ;
v_httpResp UTL_HTTP.RESP;
v_feedSource VARCHAR2(1024);
BEGIN
v_httpReq := UTL_HTTP.BEGIN_REQUEST(i_feedXmlUrl);
UTL_HTTP.SET_HEADER(
v_httpReq,
'User-Agent',
'Oracle UTL_HTTP/Oracle10g R1;'
);

UTL_HTTP.SET_HEADER(
v_httpReq,
'Content-Type',
'text/xml;charset='||i_feedXmlCharset
);

v_httpResp := UTL_HTTP.GET_RESPONSE(v_httpReq);
DBMS_LOB.CREATETEMPORARY(io_feedSourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_httpResp, v_feedSource, true);
v_feedSource := v_feedSource || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(
io_feedSourceClob,
LENGTH(v_feedSource),
v_feedSource
);
END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_httpResp);
END;
END getFeedSource;


PROCEDURE getNameSpaces(
i_feedType IN VARCHAR2,
i_feedDoc IN DBMS_XMLDOM.DomDocument,
io_feedXmlNameSpaces IN OUT NOCOPY VARCHAR2
)
IS
v_attrTagName VARCHAR2(32767);
v_feedNodelist DBMS_XMLDOM.DomNodeList;
v_nsAttrNamedNodeMap DBMS_XMLDOM.DomNamedNodeMap;
BEGIN

CASE i_feedType
WHEN C_RSS THEN
v_feedNodeList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, C_RSS);

WHEN C_RDF THEN
-- name spaceが影響しているのだと思われるが上手い解決方法が
-- 見つからなかったので、全要素を取得している。
v_feedNodeList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, '*');

WHEN C_ATOM THEN
v_feedNodeList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, C_ATOM);

END CASE;

v_nsAttrNamedNodeMap
:= DBMS_XMLDOM.GETATTRIBUTES(DBMS_XMLDOM.ITEM(v_feedNodeList, 0));

FOR i IN 0..DBMS_XMLDOM.GETLENGTH(v_nsAttrNamedNodeMap)-1 LOOP
v_attrTagName
:= DBMS_XMLDOM.GETNODENAME(DBMS_XMLDOM.ITEM(v_nsAttrNamedNodeMap, i));

IF REGEXP_INSTR(v_attrTagName, '^xmlns') = 1 THEN
io_feedXmlNameSpaces
:= io_feedXmlNameSpaces
|| v_attrTagName || '="'
|| DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.ITEM(v_nsAttrNamedNodeMap, i))
|| '" ';
END IF;
END LOOP;
END getNameSpaces;


PROCEDURE getFeedEntries(
i_feedType IN VARCHAR2,
i_feedDoc IN DBMS_XMLDOM.DomDocument,
i_feedXmlNameSpaces IN VARCHAR2,
o_feedTitle OUT NOCOPY VARCHAR2,
o_feedUrl OUT NOCOPY VARCHAR2,
o_feedEntryList OUT NOCOPY DBMS_XMLDOM.DomNodeList
)
IS
v_feedSourceXml XMLTYPE;
BEGIN
v_feedSourceXml := DBMS_XMLDOM.GETXMLTYPE(i_feedDoc);
CASE i_feedType
WHEN C_RSS THEN
o_feedEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, 'item');
o_feedTitle := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/rss/channel/title/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();
o_feedUrl := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/rss/channel/link/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();

WHEN C_RDF THEN
o_feedEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, 'item');
o_feedTitle := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/rdf:RDF/channel/title/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();
o_feedUrl := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/rdf:RDF/channel/link/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();

WHEN C_ATOM THEN
o_feedEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, 'entry');
o_feedTitle := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/feed/title/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();
o_feedUrl := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/feed/link[@type="text/html"]/@href',
i_feedXmlNameSpaces
).GETSTRINGVAL();

END CASE;
END getFeedEntries;


PROCEDURE drawFeedEntry(
i_feedEntry IN FeedEntryType
)
IS
BEGIN
HTP.TABLEROWOPEN();
HTP.TABLEDATA(
'<a href="'
|| i_feedEntry.link
|| '" style="color:#FF0000" target="_blank">'
|| i_feedEntry.title || ' -- 続きを読む... '
|| '</a>' || TO_CHAR(i_feedEntry.published,'yyyy-mm-dd hh24:mi')

);
HTP.TABLEROWCLOSE();
END drawFeedEntry;


PROCEDURE drawFeedEntries(
i_feedType IN VARCHAR2,
i_feedTitle IN VARCHAR2,
i_feedUrl IN VARCHAR2,
i_feedEntryList IN DBMS_XMLDOM.DomNodeList
)
IS
v_feedEntry FeedEntryType;
v_emptyFeedEntry FeedEntryType;
v_itemNode DBMS_XMLDOM.DomNode;
v_childnode DBMS_XMLDOM.DomNode;
v_feedItemFields DBMS_XMLDOM.DomNodeList;
v_attrNamedNodeMap DBMS_XMLDOM.DomNamedNodeMap;
v_childNodeText VARCHAR2(32767);
BEGIN
HTP.TABLEOPEN();
HTP.TABLEROWOPEN();
HTP.TABLEHEADER(
'<a href="'
|| i_feedUrl
|| '" style="color:#000000" target="_blank">'
|| i_feedTitle
|| '</a>'
|| ' - ' || dbms_xmldom.getlength(i_feedEntryList)|| ' articles.'
);
HTP.TABLEROWCLOSE();

v_feedEntry := v_emptyFeedEntry;
FOR i IN 1..DBMS_XMLDOM.GETLENGTH(i_feedEntryList) LOOP
v_itemNode := DBMS_XMLDOM.ITEM(i_feedEntryList, i-1);
v_feedItemFields := DBMS_XMLDOM.GETCHILDNODES(v_itemNode);

FOR j IN 1..DBMS_XMLDOM.GETLENGTH(v_feedItemFields) LOOP
v_childnode := DBMS_XMLDOM.ITEM(v_feedItemFields, j-1);
v_childNodeText := DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETFIRSTCHILD(v_childnode)
);

CASE DBMS_XMLDOM.GETNODENAME(v_childnode)

WHEN 'title' THEN
v_feedEntry.title := v_childNodeText;


WHEN 'link' THEN
IF i_feedType = C_ATOM THEN
-- ATOM
v_attrNamedNodeMap := DBMS_XMLDOM.GETATTRIBUTES(v_childnode);
IF DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETNAMEDITEM(v_attrNamedNodeMap, 'type')
) = 'text/html'
THEN
v_feedEntry.link :=
DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETNAMEDITEM(v_attrNamedNodeMap, 'href')
);
END IF;

ELSE
-- RSS/RDF
v_feedEntry.link := v_childNodeText;
END IF;


-- RSS 0.9x and RSS 2.0
WHEN 'pubDate' THEN
v_feedEntry.published
:= RFC822_DateStrToTimestampLTZ(v_childNodeText);

-- ATOM 1.0
WHEN 'published' THEN
v_feedEntry.published
:= RFC3339_DateStrToTimestampLTZ(v_childNodeText);

-- RSS/RDF 1.0 , RSS 2.0
WHEN 'dc:date' THEN
v_feedEntry.published
:= RFC3339_DateStrToTimestampLTZ(v_childNodeText);

-- ATOM 0.3
WHEN 'issued' THEN
v_feedEntry.published
:= RFC3339_DateStrToTimestampLTZ(v_childNodeText);

ELSE
NULL; -- nop
END CASE;
END LOOP;

drawFeedEntry(v_feedEntry);
END LOOP;
HTP.TABLECLOSE();
END drawFeedEntries;
--
--
--****************************************************************************
-- Main
--****************************************************************************
BEGIN

v_feedXmlUrl := i_feedXmlUrl;
IF v_feedXmlUrl IS NULL THEN
RAISE_APPLICATION_ERROR(-20003, 'FEEDのURLを指定してください。');
END IF;


getFeedSource(
i_feedXmlUrl => v_feedXmlUrl,
io_feedSourceClob => v_feedSourceClob
);

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(v_myParser, v_feedSourceClob);
v_feedDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);

v_rootElementTagName
:= DBMS_XMLDOM.GETTAGNAME(DBMS_XMLDOM.GETDOCUMENTELEMENT(v_feedDoc));

-- v_feedVersion
-- := DBMS_XMLDOM.GETVALUE(
-- DBMS_XMLDOM.GETATTRIBUTENODE(
-- DBMS_XMLDOM.GETDOCUMENTELEMENT(v_feedDoc),
-- C_ATTR_NAME_VERSION
-- )
-- );

getNameSpaces(
i_feedType => v_rootElementTagname,
i_feedDoc => v_feedDoc,
io_feedXmlNameSpaces => v_nsAttrXmlNameSpaces
);

getFeedEntries(
i_feedType => v_rootElementTagname,
i_feedDoc => v_feedDoc,
i_feedXmlNameSpaces => v_nsAttrXmlNameSpaces,
o_feedTitle => v_feedTitle,
o_feedUrl => v_feedUrl,
o_feedEntryList => v_feedEntryList
);

drawFeedEntries(
i_feedType => v_rootElementTagName,
i_feedTitle => v_feedTitle,
i_feedUrl => v_feedUrl,
i_feedEntryList => v_feedEntryList
);

DBMS_LOB.FREETEMPORARY(v_feedSourceClob);
DBMS_XMLDOM.FREEDOCUMENT(v_feedDoc);
DBMS_XMLPARSER.FREEPARSER(v_myParser);

EXCEPTION
WHEN OTHERS THEN
IF v_feedSourceClob IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_feedSourceClob);
END IF;
DBMS_XMLDOM.FREEDOCUMENT(v_feedDoc);
DBMS_XMLPARSER.FREEPARSER(v_myParser);
HTP.TABLEOPEN();
HTP.TABLEROWOPEN();
HTP.TABLEHEADER('RSS Reader error:'||SQLERRM());
HTP.TABLEROWCLOSE();
HTP.TABLECLOSE();
END RSS_READER;
/
show errors
/




まだまだ、早いか?! などと思っていると、あっという間に、クリスマスモードに突入しちゃうんですよね!。
聞いている曲:Take 6 - We wish you a merry christmas

| | コメント (0) | トラックバック (0)

2006年10月29日 (日)

Mac De PL/SQL RSS Reader #26

RSS Readerの続き。APEX 2.0に組み込んだRss Readerのレイアウトを変えてみた 

Hide and Show リージョンを3行2列にレイアウトしてみた。設定はこんな感じ。
Img7 Img6 

リージョンに埋め込んだコードはこんな感じ。PL/SQLブロックしか実行できないので、beginブロック内でrss_readerプロシージャを呼び出している。
Img8


実行するとこうなる。Hide and Showリージョンなのでリージョンを折り畳む事ができる。
Img2_1 Img3_1 Img4 Img5

ひとまず、こんなところで。。

| | コメント (0) | トラックバック (0)

2006年10月23日 (月)

Mac De PL/SQL RSS Reader #25

RSS Readerの続き。適当にAPEX 2.0に組み込み、一覧にしてみた。

以下の通り、大雑把に作ってみたが、それなりね。APEX (HTML DB)に慣れる必要あり。。。。
R1 R2jpg R3

| | コメント (0) | トラックバック (0)

2006年10月21日 (土)

Mac De PL/SQL RSS Reader #24

RSS Readerの続き。ドラフト版でのテストログの続き。(その6/6)

ATOM 1.0のFEEDをテストした結果。

---------------------- PROMPT ATOM 1.0
begin...
====================
Radical Imagination -from 鎌倉 with Love - 15 articles:
http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/
====================
TITLE: 由比ヶ浜秋景-3
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/3.html
Published on: 2006-10-11 19:48
—————————————-
TITLE: 老母のテラコッタ人形新作
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_58.html
Published on: 2006-10-10 00:23
—————————————-
TITLE: 地方のロードサイド風景
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_57.html
Published on: 2006-10-09 00:55
—————————————-
TITLE: 由比ヶ浜3頭会談
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_56.html
Published on: 2006-10-08 18:30
—————————————-
TITLE: 由比ヶ浜秋景-2
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/2_9.html
Published on: 2006-10-07 19:36
—————————————-
TITLE: 由比ヶ浜秋景-1
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_55.html
Published on: 2006-10-07 15:10
—————————————-
TITLE: 『ドリームボックス-殺されていくペットたち』
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_54.html
Published on: 2006-10-06 13:35
—————————————-
TITLE: 『Maria Full of Grace』(『そして、ひと粒のひかり』)
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/maria_full_of_grace.html
Published on: 2006-10-05 03:06
—————————————-
TITLE: ラ・ジュルネ(鎌倉由比ガ浜)-20 いぶりがっこ
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/20_1.html
Published on: 2006-10-04 05:03
—————————————-
TITLE: 恩師・尾崎康先生
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_53.html
Published on: 2006-10-03 13:52
—————————————-
TITLE: 朝の光
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_52.html
Published on: 2006-10-01 22:34
—————————————-
TITLE: 長谷秋色-2 曼珠沙華
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/09/2.html
Published on: 2006-09-30 00:19
—————————————-
TITLE: 今朝のおはよう-40 由比ガ浜文様
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/09/post_51.html
Published on: 2006-09-29 22:53
—————————————-
TITLE: なかむら庵(鎌倉小町)
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/09/post_50.html
Published on: 2006-09-29 21:10
—————————————-
TITLE: まっさらMac
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/09/mac.html
Published on: 2006-09-29 19:46
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH> spo off


特に問題もないので、OracleのAPEXに組み込みテストしてみる予定である。
そういえば、最近、米salesforce が、新プログラミング言語 「Apex」を発表というニュースもあり、APEX だけで検索してしまうと、いろいろとヒットしてしまう・・・・・。(^^;;

尚、コードを少々変更すれば、Oracle Portalの DBポートレット化することも難しくないと思うのだが、その環境がいまは無い。。。


クラシックも聞くんです(ただし、ピアノだけ、しかも、大映テレビのドラマで使われた曲だけ)
赤い激流
少女に何が起こったか

フジ子・へミング - 練習曲 第12番 ハ短調 作品10の12《革命》 フジ子・へミング - ラ・カンパネラ 1973 - 練習曲 第12番 ハ短調 作品10の12《革命》
フジ子・ヘミング - ラ・カンパネラ フジ子・ヘミング - 奇蹟のカンパネラ - ラ・カンパネラ (パガニーニによる大練習曲 S.141-3) [リスト]
フジ子・ヘミング - ポロネーズ第6番《英雄》 イングリット・フジコ・ヘミング - ピアノ名曲集 - ポロネーズ第6番《英雄》

今日は、美味しい空気とワインを楽しみに。。。。。どこに行ったか? 詳しくは、以下。
メガ放談
今日のゴハン

| | コメント (0) | トラックバック (0)

2006年10月20日 (金)

Mac De PL/SQL RSS Reader #23

RSS Readerの続き。ドラフト版でのテストログの続き。(その5/6)

ATOM 0.3のFEEDをテストした結果。

---------------------- PROMPT ATOM 0.3
begin...
====================
今日のゴハン - 10 articles:
http://atsu-log.way-nifty.com/today_s_menu/
====================
TITLE: 長崎堂カステラ
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_7031.html
Published on: 2006-10-11 23:46
—————————————-
TITLE: 豚汁
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_3239.html
Published on: 2006-10-11 23:36
—————————————-
TITLE: ポテトサラダ
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_e144.html
Published on: 2006-10-11 23:31
—————————————-
TITLE: TAKAGIのプリン、、、
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/takagi_71f8.html
Published on: 2006-10-10 22:24
—————————————-
TITLE: フンギビアンコ Part2
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/part2_21d3.html
Published on: 2006-10-10 22:20
—————————————-
TITLE: きのこ & アーティチョークのホットサンドウィッチ
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/__bbee.html
Published on: 2006-10-10 22:12
—————————————-
TITLE: 茶豆梅ご飯
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_cb33.html
Published on: 2006-10-10 22:04
—————————————-
TITLE: はっぴーばーすでー・ははちゃん!
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_f02c.html
Published on: 2006-10-09 23:07
—————————————-
TITLE: La vie Equiseのお総菜パン
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/la_vie_equise_0de3.html
Published on: 2006-10-09 20:36
—————————————-
TITLE: 納豆の揚げ包み焼き
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_66d1.html
Published on: 2006-10-09 09:56
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。


テストログ、ATOM 1.0へ続く。


iTMS-J、いろんなアーティストの曲がまだまだないと思っていると、The Theなんかがあったり。。。
聞いている曲:The The - NakedSelf - Swine Fever The The - NakedSelf - Swine Fever

| | コメント (0) | トラックバック (0)

2006年10月19日 (木)

Mac De PL/SQL RSS Reader #22

RSS Readerの続き。ドラフト版でのテストログの続き。(その4/6)

RSS 2.0のFEEDをテストした結果。

---------------------- PROMPT RSS 2.0
begin...
====================
Life is a trip of looking for myself ! - 15 articles:
http://miwa2006.exblog.jp
====================
TITLE: Aji & Mic -3
URL : http://miwa2006.exblog.jp/4694707
Published on: 2006-10-08 18:51
—————————————-
TITLE: 手作りごはん
URL : http://miwa2006.exblog.jp/4694041
Published on: 2006-10-08 16:17
—————————————-
TITLE: 造形の美
URL : http://miwa2006.exblog.jp/4686673
Published on: 2006-10-07 01:24
—————————————-
TITLE: 街づくりー2
URL : http://miwa2006.exblog.jp/4672126
Published on: 2006-10-04 15:48
—————————————-
TITLE: Aji & Mic -2
URL : http://miwa2006.exblog.jp/4657697
Published on: 2006-10-01 23:32
—————————————-
TITLE: 野菜収穫
URL : http://miwa2006.exblog.jp/4647062
Published on: 2006-09-30 01:29
—————————————-
TITLE: 街づくり−1
URL : http://miwa2006.exblog.jp/4641071
Published on: 2006-09-29 00:04
—————————————-
TITLE: Aji & Mic -1
URL : http://miwa2006.exblog.jp/4626283
Published on: 2006-09-26 14:16
—————————————
TITLE: 自由が丘
URL : http://miwa2006.exblog.jp/4625821
Published on: 2006-09-26 11:55
—————————————-
TITLE: 増山理人「中南米ニカラグア・スラムの子どもたちと過ごした2年間の記憶」講演会
URL : http://miwa2006.exblog.jp/4601697
Published on: 2006-09-22 11:48
—————————————-
TITLE: Love! dessert
URL : http://miwa2006.exblog.jp/4600028
Published on: 2006-09-22 00:39
—————————————-
TITLE: 愛すべきタマゴサンド
URL : http://miwa2006.exblog.jp/4568432
Published on: 2006-09-16 23:45
—————————————-
TITLE: 料理してますよ。
URL : http://miwa2006.exblog.jp/4559138
Published on: 2006-09-15 11:25
—————————————-
TITLE: レンバイ
URL : http://miwa2006.exblog.jp/4395219
Published on: 2006-08-23 10:28
—————————————-
TITLE: Mic夏バテ?
URL : http://miwa2006.exblog.jp/4387154
Published on: 2006-08-22 10:47
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。

テストログ、ATOM 0.3へ続く。


日本のバンドだけど、いいねぇ。ちょいとラテン入ってる?!
聞いている曲:ピラミッド − ピラミッド ピラミッド - ピラミッド

| | コメント (0) | トラックバック (0)

2006年10月18日 (水)

Mac De PL/SQL RSS Reader #21

RSS Readerの続き。ドラフト版でのテストログの続き。(その3/6)

RDF (RSS 1.0) のFEEDをテストした結果。
RSS 0.91で登場したmegawattさんのブログなのだが、RDFでは記事の公開日が入っている。

---------------------- PROMPT RDF
begin...
====================
メガ放談 - 16 articles:
http://megawatt.blogdns.net/blog
====================
TITLE: アレルギーフリーな猫
URL : http://megawatt.blogdns.net/blog/304
Published on: 2006-10-11 16:42
—————————————-
TITLE: 猫は段ボールがお好き
URL : http://megawatt.blogdns.net/blog/303
Published on: 2006-10-10 11:16
—————————————-
TITLE: オクトーバーフェストに行ってきた
URL : http://megawatt.blogdns.net/blog/302
Published on: 2006-10-08 22:37
—————————————-
TITLE: オクトーバーフェストに行ってくる
URL : http://megawatt.blogdns.net/blog/301
Published on: 2006-10-07 22:30
—————————————-
TITLE: Old People
URL : http://megawatt.blogdns.net/blog/300
Published on: 2006-10-07 00:08
—————————————-
TITLE: ラップ音≠rap sounds
URL : http://megawatt.blogdns.net/blog/299
Published on: 2006-10-03 09:51
—————————————-
TITLE: 猫のための写真講座/2006年度前期・6
URL : http://megawatt.blogdns.net/blog/298
Published on: 2006-10-01 12:41
—————————————-
TITLE: 傷つきたくないからコミュニケーションしないという意見がある
URL : http://megawatt.blogdns.net/blog/297
Published on: 2006-09-28 13:23
—————————————-
TITLE: 英会話の日々
URL : http://megawatt.blogdns.net/blog/296
Published on: 2006-09-26 11:55
—————————————-
TITLE: コミュニケーション能力の減衰を食い止めるには
URL : http://megawatt.blogdns.net/blog/295
Published on: 2006-09-21 19:23
—————————————-
TITLE: くどかれました!?
URL : http://megawatt.blogdns.net/blog/294
Published on: 2006-09-19 21:43
—————————————-
TITLE: 大手町・日本工業倶楽部
URL : http://megawatt.blogdns.net/blog/293
Published on: 2006-09-18 12:59
—————————————-
TITLE: 役目を終える日
URL : http://megawatt.blogdns.net/blog/292
Published on: 2006-09-16 22:13
—————————————-
TITLE: 左向け〜
URL : http://megawatt.blogdns.net/blog/291
Published on: 2006-09-15 09:07
—————————————-
TITLE: 新しいiPod shuffleは買い、かなあ
URL : http://megawatt.blogdns.net/blog/290
Published on: 2006-09-14 16:15
—————————————-
TITLE: びーの枕
URL : http://megawatt.blogdns.net/blog/289
Published on: 2006-09-11 22:39
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。

テストログ、RSS 2.0へ続く。


そう言えば、小曽根真さんのBluenote Tokyoでのライブは、話も楽しい。
聞いている曲:小曽根真トリオ − Real 小曽根 真トリオ - Real - ダンス・オン・ザ・ビーチ

| | コメント (0) | トラックバック (0)

2006年10月17日 (火)

Mac De PL/SQL RSS Reader #20

RSS Readerの続き。ドラフト版でのテストログの続き。 (その2/6)。

RSS 0.92のFEEDをテストした結果(これも公開日が省略されている)

---------------------- PROMPT RSS 0.92
begin...
====================
AMIS Technology blog - 10 articles:
http://technology.amis.nl/blog
====================
TITLE: Rule based in Oracle 10g
URL : http://technology.amis.nl/blog/?p=1354
—————————————-
TITLE: Putting Analytical Functions to good use - find tables with multiple
foreign keys to the same referenced table
URL : http://technology.amis.nl/blog/?p=1353
—————————————-
TITLE: Extract Domain Definitions from Oracle Designer for use in JHeadstart
URL : http://technology.amis.nl/blog/?p=1352
—————————————-
TITLE: JHeadstart 10.1.3 Evaluation Copy available! - Everybody can now try out
JHeadstart for ADF Faces
URL : http://technology.amis.nl/blog/?p=1351
—————————————-
TITLE: SUSE support for next release of Oracle
URL : http://technology.amis.nl/blog/?p=1350
—————————————-
TITLE: JHeadstart 10.1.3 - Generating InputTextHyperlink items -
a generic custom generator template
URL : http://technology.amis.nl/blog/?p=1349
—————————————-
TITLE: ADF Faces: The InputTextHyperlink Component
URL : http://technology.amis.nl/blog/?p=1348
—————————————-
TITLE: Oracle BPEL PM 10.1.3 - Sending an Email to multiple recipients
URL : http://technology.amis.nl/blog/?p=1347
—————————————-
TITLE: Steve Muench publishes tutorial for JHeadstart 10.1.3 for ADF Faces
URL : http://technology.amis.nl/blog/?p=1346
—————————————-
TITLE: Unit testing with XFire ? How to test your SOAP server with a WSDL file
URL : http://technology.amis.nl/blog/?p=1345
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。


テストログ、RDF (RSS 1.0)へ続く。


ボコーダーで「ド・モ・ア・リ・ガ・ト・ミ・ス・タ・ー・ロ・ボ・ッ・ト」というところ、懐かしいですね。 思い切って、ボコーダーを使うという今時の勇気あるミュージシャン居ないかねぇ。(意外と、ウケたりして・・・)
聞いている曲: Styx - Styx Greatest Hits - Mr. RobotStyx - Styx: Greatest Hits - Mr. Roboto

| | コメント (0) | トラックバック (0)

2006年10月16日 (月)

Mac De PL/SQL RSS Reader #19

RSS Readerの続き。課題をクリアしたドラフト版でのテスト結果。
尚、ログが長いので、今回から、6回に分けて公開していく。(そんなに引っ張るなよ〜という声が遠くでするが・・・マイペース。)

テスト用のスクリプトは以下。

GLASSCATFISH> set serveroutput on
GLASSCATFISH> !cat rss_reader.sql
PROMPT -----------------------
PROMPT RSS 0.91
execute rss_reader('http://megawatt.blogdns.net/blog/rdf91_xml');
PROMPT -----------------------
PROMPT RSS 0.92
execute rss_reader('http://technology.amis.nl/blog/?feed=rss');
PROMPT -----------------------
PROMPT RDF
execute rss_reader('http://megawatt.blogdns.net/blog/rdf10_xml');
PROMPT -----------------------
PROMPT RSS 2.0
execute rss_reader('http://miwa2006.exblog.jp/index.xml');
PROMPT -----------------------
PROMPT ATOM 0.3
execute rss_reader('http://atsu-log.way-nifty.com/today_s_menu/atom.xml');
PROMPT -----------------------
PROMPT ATOM 1.0
execute rss_reader('http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/atom.xml');

RSS 0.91のFEEDをテストした結果。(公開日が省略されている)

GLASSCATFISH> @rss_reader
---------------------- PROMPT RSS 0.91
begin...
====================
メガ放談 - 16 articles:
http://megawatt.blogdns.net/blog
====================
TITLE: アレルギーフリーな猫
URL : http://megawatt.blogdns.net/blog/304
—————————————-
TITLE: 猫は段ボールがお好き
URL : http://megawatt.blogdns.net/blog/303
—————————————-
TITLE: オクトーバーフェストに行ってきた
URL : http://megawatt.blogdns.net/blog/302
—————————————-
TITLE: オクトーバーフェストに行ってくる
URL : http://megawatt.blogdns.net/blog/301
—————————————-
TITLE: Old People
URL : http://megawatt.blogdns.net/blog/300
—————————————-
TITLE: ラップ音≠rap sounds
URL : http://megawatt.blogdns.net/blog/299
—————————————-
TITLE: 猫のための写真講座/2006年度前期・6
URL : http://megawatt.blogdns.net/blog/298
—————————————-
TITLE: 傷つきたくないからコミュニケーションしないという意見がある
URL : http://megawatt.blogdns.net/blog/297
—————————————-
TITLE: 英会話の日々
URL : http://megawatt.blogdns.net/blog/296
—————————————-
TITLE: コミュニケーション能力の減衰を食い止めるには
URL : http://megawatt.blogdns.net/blog/295
—————————————-
TITLE: くどかれました!?
URL : http://megawatt.blogdns.net/blog/294
—————————————-
TITLE: 大手町・日本工業倶楽部
URL : http://megawatt.blogdns.net/blog/293
—————————————-
TITLE: 役目を終える日
URL : http://megawatt.blogdns.net/blog/292
—————————————-
TITLE: 左向け〜
URL : http://megawatt.blogdns.net/blog/291
—————————————-
TITLE: 新しいiPod shuffleは買い、かなあ
URL : http://megawatt.blogdns.net/blog/290
—————————————-
TITLE: びーの枕
URL : http://megawatt.blogdns.net/blog/289
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。

テストログ、RSS 0.92へつづく。


今週から、Bluenote Tokyoで Candy Dulferのライブですね。ファンキーなサックスを楽しむのもいいかも。(そういえば、Candy Dulferのライブに行ったのはもう2年前くらいだったか? 昨年のMarcus Miller、今年のDave Koz Dave Koz - The Dance のライブの次に面白しいライブでした。)今年も楽しませてくれることでしょう。

| | コメント (0) | トラックバック (0)

2006年10月14日 (土)

Mac De PL/SQL RSS Reader #18

RSS Readerの続き。問題点の回避方法。

以下は、各FEEDのルート要素を示したものだが、違いがお分かりだろうか?

<rss version="0.92">

<rss version="0.91">

<rss version="2.0"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:cc="http://web.resource.org/cc/"
xmlns="http://purl.org/rss/1.0/">

<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns="http://purl.org/rss/1.0/">

<feed version="0.3"
 xmlns="http://purl.org/atom/ns#"
 xmlns:dc="http://purl.org/dc/elements/1.1/">

<feed xmlns="http://www.w3.org/2005/Atom">

もう、気付きましたよね?! そう!。 違いは、Namespaceが宣言されている点なのである。
しかも、同じ RDFでも微妙に異なる場合もある。ということで、ORA-30625というエラーの原因は、Namespaceを指定すれば解決できそうである。

残りのORA-31011については、解析に失敗していことから、おそらく、文字化けが影響しているものと想像できる。(以前にも似たようなことがあったが文字化けを回避することで解決した。

それらを踏まえてテスト用のコードを修正(前回のコードに比べると可成りコード量が増えます)し再度、確認してみると、

RSS 2.0ーー(前回はこんなエラーであった。

GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns:dc="http://purl.org/dc/elements/1.1/" '
12 ||'xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" '
13 ||'xmlns:admin="http://webns.net/mvcb/" '
14 ||'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"';
15 begin
16 v_req := UTL_HTTP.BEGIN_REQUEST('http://miwa2006.exblog.jp/index.xml');
17 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
18 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
19 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
20 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
21 BEGIN
22 LOOP
23 UTL_HTTP.READ_LINE(v_resp, v_source, true);
24 v_source := v_source || UTL_TCP.CRLF;
25 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
26 END LOOP;
27 EXCEPTION
28 WHEN UTL_HTTP.END_OF_BODY THEN
29 UTL_HTTP.END_RESPONSE(v_resp);
30 END;
31 v_myParser := DBMS_XMLPARSER.NEWPARSER();
32 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
33 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
34 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
35 dbms_output.put_line(
36 XmlType.extract(
37 v_xml, '/rss/channel/title/text()', c_namespace
38 ).getStringVal()
39 );
40 dbms_output.put_line(
41 XmlType.extract(
42 v_xml, '/rss/channel/link/text()', c_namespace
43 ).getStringVal()
44 );
45* end;
GLASSCATFISH> /
Life is a trip of looking for myself !
http://miwa2006.exblog.jp

PL/SQLプロシージャが正常に完了しました。

RDFーー(前回はこのようなエラーであった。

GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '
12 ||'xmlns:dc="http://purl.org/dc/elements/1.1/" '
13 ||'xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" '
14 ||'xmlns:admin="http://webns.net/mvcb/" '
15 ||'xmlns:content="http://purl.org/rss/1.0/modules/content/" '
16 ||'xmlns:cc="http://web.resource.org/cc/" '
17 ||'xmlns="http://purl.org/rss/1.0/"';
18 begin
19 v_req := UTL_HTTP.BEGIN_REQUEST(
20 'http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/index.rdf'
21 );
22 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
23 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
24 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
25 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
26 BEGIN
27 LOOP
28 UTL_HTTP.READ_LINE(v_resp, v_source, true);
29 v_source := v_source || UTL_TCP.CRLF;
30 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
31 END LOOP;
32 EXCEPTION
33 WHEN UTL_HTTP.END_OF_BODY THEN
34 UTL_HTTP.END_RESPONSE(v_resp);
35 END;
36 v_myParser := DBMS_XMLPARSER.NEWPARSER();
37 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
38 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
39 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
40 dbms_output.put_line(
41 XmlType.extract(
42 v_xml, '/rdf:RDF/channel/title/text()', c_namespace
43 ).getStringVal()
44 );
45 dbms_output.put_line(
46 XmlType.extract(
47 v_xml, '/rdf:RDF/channel/link/text()', c_namespace
48 ).getStringVal()
49 );
50* end;
GLASSCATFISH> /
Mac De Oracle
http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '
12 ||'xmlns:dc="http://purl.org/dc/elements/1.1/" '
13 ||'xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" '
14 ||'xmlns:admin="http://webns.net/mvcb/" '
15 ||'xmlns="http://purl.org/rss/1.0/"';
16 begin
17 v_req := UTL_HTTP.BEGIN_REQUEST(
18 'http://megawatt.blogdns.net/blog/rdf10_xml'
19 );
20 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
21 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
22 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
23 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
24 BEGIN
25 LOOP
26 UTL_HTTP.READ_LINE(v_resp, v_source, true);
27 v_source := v_source || UTL_TCP.CRLF;
28 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
29 END LOOP;
30 EXCEPTION
31 WHEN UTL_HTTP.END_OF_BODY THEN
32 UTL_HTTP.END_RESPONSE(v_resp);
33 END;
34 v_myParser := DBMS_XMLPARSER.NEWPARSER();
35 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
36 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
37 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
38 dbms_output.put_line(
39 XmlType.extract(
40 v_xml, '/rdf:RDF/channel/title/text()', c_namespace
41 ).getStringVal()
42 );
43 dbms_output.put_line(
44 XmlType.extract(
45 v_xml, '/rdf:RDF/channel/link/text()', c_namespace
46 ).getStringVal()
47 );
48* end;
GLASSCATFISH> /
メガ放談
http://megawatt.blogdns.net/blog

PL/SQLプロシージャが正常に完了しました。

最後にATOMーー(前回はこのようなエラーであった

GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns="http://purl.org/atom/ns#" '
12 ||'xmlns:dc="http://purl.org/dc/elements/1.1/"';
13 begin
14 v_req := UTL_HTTP.BEGIN_REQUEST(
15 'http://atsu-log.way-nifty.com/today_s_menu/atom.xml'
16 );
17 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
18 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
19 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
20 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
21 BEGIN
22 LOOP
23 UTL_HTTP.READ_LINE(v_resp, v_source, true);
24 v_source := v_source || UTL_TCP.CRLF;
25 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
26 END LOOP;
27 EXCEPTION
28 WHEN UTL_HTTP.END_OF_BODY THEN
29 UTL_HTTP.END_RESPONSE(v_resp);
30 END;
31 v_myParser := DBMS_XMLPARSER.NEWPARSER();
32 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
33 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
34 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
35 dbms_output.put_line(
36 XmlType.extract(
37 v_xml, '/feed/title/text()', c_namespace
38 ).getStringVal()
39 );
40 dbms_output.put_line(
41 XmlType.extract(
42 v_xml, '/feed/link[@type="text/html"]/@href', c_namespace
43 ).getStringVal()
44 );
45* end;
GLASSCATFISH> /
今日のゴハン
http://atsu-log.way-nifty.com/today_s_menu/

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH>
GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns="http://www.w3.org/2005/Atom"';
12 begin
13 v_req := UTL_HTTP.BEGIN_REQUEST(
14 'http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/atom.xml'
15 );
16 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
17 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
18 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
19 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
20 BEGIN
21 LOOP
22 UTL_HTTP.READ_LINE(v_resp, v_source, true);
23 v_source := v_source || UTL_TCP.CRLF;
24 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
25 END LOOP;
26 EXCEPTION
27 WHEN UTL_HTTP.END_OF_BODY THEN
28 UTL_HTTP.END_RESPONSE(v_resp);
29 END;
30 v_myParser := DBMS_XMLPARSER.NEWPARSER();
31 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
32 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
33 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
34 dbms_output.put_line(
35 XmlType.extract(
36 v_xml, '/feed/title/text()', c_namespace
37 ).getStringVal()
38 );
39 dbms_output.put_line(
40 XmlType.extract(
41 v_xml, '/feed/link[@type="text/html"]/@href', c_namespace
42 ).getStringVal()
43 );
44* end;
GLASSCATFISH> /
Radical Imagination -from 鎌倉 with Love
http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH>

ということで、全て解決!!。




ほんとうに曲数が少ないのは iTMSの抱える課題だ。ということで、今回もAmazonへ

聞いている曲:Candy Dulfer - ベスト・オブ・キャンディ・ダルファー

| | コメント (0) | トラックバック (0)

2006年10月13日 (金)

Mac De PL/SQL RSS Reader #17

RSS Readerの続きです。
さて、RSSリーダーを作る上でもう一つクリアしておきたい課題がある。
それは、各記事のタイトルとURL、公開日以外に、各FEEDのタイトルとURLを取得すること。

BLOGに関して、それぞれの記事のタイトルとURL以外に、BLOGのタイトルとURLも表示したいと考えている。
作成中のRSSリーダーでは、DOMを利用していので、そのBLOGのタイトルとURLもDOMをトラバースして取得することも可能なのだが、ロジックが複雑になるため、BLOGのタイトルとURLに関しては、XPATHを利用して取り出すことにした。

当初、DBMS_XMLPARSER.PARSE(URL)を利用しようとしていたが、URL指定でパースした場合にマルチバイト文字で文字化けが発生したため、UTL_HTTPパッケージDBMS_XMLPARSER.PARSECLOB(CLOB)を使用して回避している。XPATHを利用しBLOGタイトルとURIの取得テストでは、DBMS_XMLPARSER.PARSE(URL)同様に文字化けするのだが、HttpUriType型を利用してXML(XmlType型)を取り出し、XPATHでBLOGタイトルとURLを取得することにした。
HttpUriType型と、XmlType型の2つはどちらもオブジェクト型である。詳細は、マニュアル「PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス」のXmlTypeHttpUriType参照のこと。

以下は、RSS 0.92 の FEEDである「AMIS Technorogy blog」のタイトルとURLをXPATHを利用して取り出したもの。シングルバイトなので文字化けは起こらない。楽でいいね〜。マルチバイト文字が含まれていても文字化けしなくなれば、この方法が利用できるようになるので楽なのだが、Oracleさんなんとかして。。。

GLASSCATFISH> set serveroutput on
GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://technology.amis.nl/blog/?feed=rss');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rss/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rss/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
AMIS Technology blog
http://technology.amis.nl/blog

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH>

ところが、友人のmegawattさんの「メガ放談」(RSS 0.91) のタイトルとURLをXPATHを利用して取り出すと、タイトルは見事に文字化けする。DBMS_XMLPARSER.PARSE(URL)を利用した場合と同じく文字化けするが、取り出せることは取り出せる。文字化けの回避方法はあるのでとりあえずこのままテスト続行!。

GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://megawatt.blogdns.net/blog/rdf91_xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rss/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rss/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
a?!a?¬a??e≪?
http://megawatt.blogdns.net/blog

PL/SQLプロシージャが正常に完了しました。

3つ目は、RSS 2.0なのだが、RSS 0.9xとは異なりエラーとなる。何故?
幸か不幸か、今回は、RSS 0.9x以外のFEEDフォーマットにも対応しなければならない。

GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://miwa2006.exblog.jp/index.xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rss/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rss/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00225: 要素の終了タグ"item"が開始タグ"title"と一致しません
Error at line 94
中にエラーが発生しました
ORA-06512: "SYS.XMLTYPE", 行5
ORA-06512: "SYS.HTTPURITYPE", 行97
ORA-06512: 行6


GLASSCATFISH>

つづいて、RDF (RSS 1.0)を試す。どちらも、RDFなのだが上手くいかない。しかも、エラーメッセージがそれぞれ異なる。なぜ?? 

GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/index.rdf');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rdf:RDF/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rdf:RDF/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00225: 要素の終了タグ"channel"が開始タグ"description"と一致しません
Error at line 42
中にエラーが発生しました
ORA-06512: "SYS.XMLTYPE", 行5
ORA-06512: "SYS.HTTPURITYPE", 行97
ORA-06512: 行6


GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://megawatt.blogdns.net/blog/rdf10_xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rdf:RDF/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rdf:RDF/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-30625: NULL SELF引数のメソッド・ディスパッチは使用できません
ORA-06512: 行7


GLASSCATFISH>


最後にATOM。結果は、RSS 2.0、RDF、ATOMは撃沈である。ここでも、エラー内容がそれぞれ異なる。
この方法では、上手くいったのは、RSS 0.9xのみ。 どうする。。 (><)。
GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://atsu-log.way-nifty.com/today_s_menu/atom.xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/feed/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/feed/link[@type="text/html"]/@href').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00225: 要素の終了タグ"a"が開始タグ"p"と一致しません
Error at line 30
中にエラーが発生しました
ORA-06512: "SYS.XMLTYPE", 行5
ORA-06512: "SYS.HTTPURITYPE", 行97
ORA-06512: 行6

GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/atom.xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/feed/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/feed/link[@type="text/html"]/@href').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-30625: NULL SELF引数のメソッド・ディスパッチは使用できません
ORA-06512: 行7


GLASSCATFISH>

これらの解決方法は????

エラーメッセージもいろいろ。上記のコードを眺めていても原因は全く浮かばない。

視点を変え、各FEEDのXMLソースを眺めると、RSS 0.9xとRSS2.0、RDF、ATOMのXMLには異なる点があるのみ気付く。それが何か分かりますか? このエラー原因の一なのである。
http://technology.amis.nl/blog/?feed=rss
http://megawatt.blogdns.net/blog/rdf91_xml
http://miwa2006.exblog.jp/index.xml
http://megawatt.blogdns.net/blog/rdf10_xml
http://atsu-log.way-nifty.com/today_s_menu/atom.xml
http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/atom.xml


今日はここまで、次回はこれらの回避方法。



聞いている曲:え〜〜と、iTMSにはこれもありませんでした。。Gloria Estefan & Miami Sound Machine - 1.2.3

| | コメント (0) | トラックバック (0)

2006年10月12日 (木)

Mac De PL/SQL RSS Reader #16

前回のつづき。rfc3339の日付/日時フォーマット対応ストアドプロシージャのソースコードは以下。。

create or replace FUNCTION RFC3339_DateStrToTimeStampLTZ
(
i_dateTimeString IN VARCHAR2
)
RETURN TIMESTAMP WITH LOCAL TIME ZONE
AS
v_tempTimeStampTz TIMESTAMP WITH LOCAL TIME ZONE := NULL;
v_dateTimeString VARCHAR2(50) := NULL;
v_timeStampTzFormat VARCHAR2(40) := NULL;
c_nls_date_language CONSTANT VARCHAR2(40) := 'NLS_DATE_LANGUAGE=AMERICAN';
BEGIN
v_dateTimeString := REGEXP_REPLACE(
REGEXP_REPLACE(
UPPER(i_dateTimeString),
'T', NULL, 1, 1
),
'Z$', 'UTC'
);

IF v_dateTimeString IS NULL THEN
RETURN NULL;
END IF;


v_timeStampTzFormat := 'RRRR-MM-DD';

IF LENGTH(v_dateTimeString) >= 10 THEN

IF REGEXP_INSTR(v_dateTimeString , '([0-9]{2}:){2}[0-9]{2}\.?') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI:SSXFF';
END IF;

IF REGEXP_INSTR(v_dateTimeString, '(\+|\-)[0-9]{2}:[0-9]{2}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZH:TZM';
ELSIF REGEXP_INSTR(v_dateTimeString, 'UTC$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZR';
END IF;
END IF;

v_tempTimeStampTz := TO_TIMESTAMP_TZ(
v_dateTimeString,
v_timeStampTzFormat,
c_nls_date_language
);

RETURN v_tempTimeStampTz;

EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(
-20002,
'RFC3339_DateStrToTimeStampLTZ():' || SQLERRM()
);
END;
/
前々回も書いたように、入力される文字列はrfc3339日付/日時フォーマットを前提としているため、入力書式の厳密なチェックなどは行っていない。
聞いている曲:
やはり、80sにはすばらしい曲、というか記憶に残る曲が多いよね。 まぁ、このAvalonに関しては、日産のCMで使われたりしたので最近の曲? という方も多いのだけれど。。。
Roxy Music - Avalon - The Space Between Roxy Music - Avalon - The Space Between

| | コメント (0) | トラックバック (0)

2006年10月11日 (水)

Mac De PL/SQL RSS Reader #15

前回のつづき。簡単なテスト。

GLASSCATFISH> !cat rfc3339_func_test.sql
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02.25Z') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02Z') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02+09:00') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02-09:00') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02.25-09:00') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02.25+09:00') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13') from dual;

GLASSCATFISH> @rfc3339_func_test

RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02.25Z')
---------------------------------------------------------------------------
03-12-14 03:30:02.250000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02Z')
---------------------------------------------------------------------------
03-12-14 03:30:02.000000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02+09:00')
---------------------------------------------------------------------------
03-12-13 18:30:02.000000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02-09:00')
---------------------------------------------------------------------------
03-12-14 12:30:02.000000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02.25-09:00')
---------------------------------------------------------------------------
03-12-14 12:30:02.250000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02.25+09:00')
---------------------------------------------------------------------------
03-12-13 18:30:02.250000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13')
---------------------------------------------------------------------------
03-12-13 00:00:00.000000000

GLASSCATFISH>

rfc822よりはシンプルね。

今日はここまで。次回はソースコードを載せる予定。



聞いている曲:iTMS Japanの曲の少なさはまだまだ改善されず。。。まあ、Tribute Albumも悪くないんですが、やはり、オリジナルも聞きたいわけで。。。iTMS Japanに無いものはAmazonか。。
Sade Tribute Band - Smooth Sax Tribute To Sade Sade Tribute Band - Smooth Sax Tribute To Sade - Smooth Operator



| | コメント (0) | トラックバック (0)

2006年10月10日 (火)

Mac De PL/SQL RSS Reader #14

前回につづき、今回は、rfc3339の日付/時間フォーマット向けに、暫定版として RFC3339_DateStrToTimeStampLTZ()というストアドプロシージャを作ってみた。この関数も、rfc3339日付/時間フォーマットを文字列として入力し、TIMESTAMP WITH LOCAL TIME ZONE型で返すようにした。

尚、rfc3339で規定されている time-offset の "Z"は、ストアドファンクション内部で "UTC"に変換して扱うことにした。

また、入力する文字列もrfc3339の日付/時間フォーマットであることを前提とし、 RFC3339_DateStrToTimeStampLTZ()ファンクション内部ではフォーマットの厳密な等は行わない。(但し、オラクルのTO_TIMESTAMP_TZ()関数では、オラクルの日付/時間書式に対するチェックは行われる。)


次回は、簡単なテストとソースコードを載せる予定。


秋、おいしいワインの新酒が楽しみな季節になってきました。今年のできはどうなんだろう? などど思いながら、私のお気に入り、高畠ワイナリーのブログを見ると、、、「予想以上」というタイトル!。 しかし、ワインの話ではなく、昨日まで開催さてていた、恒例の「秋の収穫祭」の来場者の話題でした。。。(^^;;

ところで、高畠ワイナリーさん主催のワインセミナーがあったと記憶しているが、最近はどうなんだろう?。ホームページを見ても書いていないので、時間が取れそうなら確認してみようかと。

以前(といっても、もう7年も前だが)、私も参加したことがある。高畠ワイナリーで生産しているワインをテイスティングしてワインの楽しみ方を知るというもの(とは言っても、入門レベルだけど、これが結構楽しい)

その時に貰ったセミナーの終了証がこれ。(ちなみにワインセミナーは、ワイナリー内で行われていたので、当日は、新幹線で日帰りした記憶が・・・・・。結構、飲む事になるので、車では絶対行けませんよ。)

Takahata_wine_certified

奥さんのブログ「今日のゴハン」でもなんどか書いてましたね。

| | コメント (0) | トラックバック (0)

2006年10月 9日 (月)

Mac De PL/SQL RSS Reader #13

前回の続き。ストアドファンクションrfc822_dateStrToTimestampLTZ()のソースコードは以下の通り。

CREATE OR REPLACE FUNCTION RFC822_DateStrToTimeStampLTZ
(
i_dateTimeString IN VARCHAR2
)
RETURN TIMESTAMP WITH LOCAL TIME ZONE
AS
v_tempTimeStampTz TIMESTAMP WITH LOCAL TIME ZONE := NULL;
v_dateTimeString VARCHAR2(50) := NULL;
v_timeStampTzFormat VARCHAR2(40) := NULL;
c_nls_date_language CONSTANT VARCHAR2(40) := 'NLS_DATE_LANGUAGE=AMERICAN';
BEGIN
v_dateTimeString := UPPER(i_dateTimeString);
IF v_dateTimeString IS NULL THEN
RETURN NULL;
END IF;

IF REGEXP_INSTR(v_dateTimeString, '^[A-Z]{3}\, ') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'DY, ';
END IF;

v_timeStampTzFormat := v_timeStampTzFormat || 'DD MON RRRR';

IF REGEXP_INSTR(v_dateTimeString, '[0-9]{2}:[0-9]{2}:[0-9]{2}') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI:SS ';
ELSIF REGEXP_INSTR(v_dateTimeString, '[0-9]{2}:[0-9]{2}') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI ';
END IF;

IF REGEXP_INSTR(v_dateTimeString, ' (\+|\-)[0-9]{4}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZHTZM';
ELSIF REGEXP_INSTR(v_dateTimeString, ':[0-9]{2}$') = 0
AND REGEXP_INSTR(v_dateTImeString, '[0-9]{2} [A-Z]{3} [0-9]{2,4}$') = 0
AND REGEXP_INSTR(v_dateTImeString, ' [A-Z]{1,3}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZR';
END IF;

v_tempTimeStampTz := TO_TIMESTAMP_TZ(
v_dateTimeString,
v_timeStampTzFormat,
c_nls_date_language
);

RETURN v_tempTimeStampTz;

EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(
-20001,
'RFC822_DateStrToTimeStampLTZ():' || SQLERRM()
);
END;
/

というように、日付/時間文字列を一旦、TO_TIMESTAMP_TZ()関数でTIMESTAMP WITH TIME ZONE型に変換する。この時点でタイムゾーンリージョンが指定されていれば、夏時間も考慮され変換される。最終的に、TIMESTAMP WITH LOCAL TIME ZONE型で返すようにした。(尚、入力される日付/日時文字列が、RFC822形式であることを前提にしているため文字列妥当性などのチェックは厳密は行っていない。)

・・・・ファンクション名は変えたほうがいいか・・・・



聞いている曲:今日もSmooth Jazzで。
Warren Hill - Popjazz - Toronto Warren Hill - Popjazz - Toronto

| | コメント (0) | トラックバック (0)

2006年10月 8日 (日)

Mac De PL/SQL RSS Reader #12

PL/SQL RSS Readerの続きです。では、早速、rfc822_dateStrToTimestampLTZ()のテストから、

GLASSCATFISH> !cat rfc822_func_test.sql
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 GMT') from dual;
select rfc822_datestrtotimestampltz('07 Sep 2002 00:00:01 GMT') from dual;
select rfc822_datestrtotimestampltz('07 Sep 02 00:00:01 GMT') from dual;
select rfc822_datestrtotimestampltz('07 Sep 02 00:00 GMT') from dual;
select rfc822_datestrtotimestampltz('07 Sep 02') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 02 00:00:01 +0900') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 02 00:00:01 -0900') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 EST') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 CST') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 MST') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 PST') from dual;
select rfc822_datestrtotimestampltz('Sun, 8 Oct 2006 07:00:00 +0900') from dual;
select rfc822_datestrtotimestampltz('Sat, 7 Oct 2006 22:00:00 GMT') from dual;
PROMPT 夏時間の確認
select rfc822_datestrtotimestampltz('7 Oct 2006 18:00:00 EST') from dual;
select rfc822_datestrtotimestampltz('7 Oct 2006 18:00:00 -0500') from dual;
select rfc822_datestrtotimestampltz('7 Oct 2006 18:00:00 -0400') from dual;
select rfc822_datestrtotimestampltz('31 Oct 2006 22:00:00 EST') from dual;
select rfc822_datestrtotimestampltz('31 Oct 2006 22:00:00 -0500') from dual;
select rfc822_datestrtotimestampltz('31 Oct 2006 22:00:00 -0400') from dual;
PROMPT オラクルのタイムゾーンリージョンに無いコード
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 EDT') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 CDT') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 MDT') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 PDT') from dual;
--
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 UT') from dual;


GLASSCATFISH> @rfc822_func_test

RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01GMT')
---------------------------------------------------------------------------
02-09-07 09:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('07SEP200200:00:01GMT')
---------------------------------------------------------------------------
02-09-07 09:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('07SEP0200:00:01GMT')
---------------------------------------------------------------------------
02-09-07 09:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('07SEP0200:00GMT')
---------------------------------------------------------------------------
02-09-07 09:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('07SEP02')
---------------------------------------------------------------------------
02-09-07 00:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP0200:00:01+0900')
---------------------------------------------------------------------------
02-09-07 00:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP0200:00:01-0900')
---------------------------------------------------------------------------
02-09-07 18:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01EST')
---------------------------------------------------------------------------
02-09-07 13:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01CST')
---------------------------------------------------------------------------
02-09-07 14:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01MST')
---------------------------------------------------------------------------
02-09-07 15:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01PST')
---------------------------------------------------------------------------
02-09-07 16:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SUN,8OCT200607:00:00+0900')
---------------------------------------------------------------------------
06-10-08 07:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,7OCT200622:00:00GMT')
---------------------------------------------------------------------------
06-10-08 07:00:00.000000000

夏時間の確認

RFC822_DATESTRTOTIMESTAMPLTZ('7OCT200618:00:00EST')
---------------------------------------------------------------------------
06-10-08 07:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('7OCT200618:00:00-0500')
---------------------------------------------------------------------------
06-10-08 08:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('7OCT200618:00:00-0400')
---------------------------------------------------------------------------
06-10-08 07:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('31OCT200622:00:00EST')
---------------------------------------------------------------------------
06-11-01 12:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('31OCT200622:00:00-0500')
---------------------------------------------------------------------------
06-11-01 12:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('31OCT200622:00:00-0400')
---------------------------------------------------------------------------
06-11-01 11:00:00.000000000

オラクルのタイムゾーンリージョンに無いコード
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 EDT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48


select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 CDT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48v

select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 MDT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48


select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 PDT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48


select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 UT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48


GLASSCATFISH>

と、このような感じになる。夏時間は自動計算されているようだ。
ということは・・・、"EDT"/"CDT"/"MDT"/"PDT"は単純に"EST"/"CST"/"MST"/"PST"に置換するだけで対応できるかも!?

テストのログが長くなってしまったので、今日はここまで。ストアドファンクションのソースコードは次回。



いろいろと行事があって、少々疲れ気味。。。やはりこんなときは、Smooth Jazz....
ということで、今日も Internet Radio SmoothJazz.com

| | コメント (0) | トラックバック (0)

2006年10月 7日 (土)

Mac De PL/SQL RSS Reader #11

PL/SQLで RSS Readerの続きです。

feedの日付/時間は、rfc822または、rfc3339に準拠ということだった。
今回は、元のタイムゾーンは重要ではないので、timestamp with local time zone型に変換して持つことにした。

まず、暫定だがrfc822向けに、rfc822_dateStrToTimestampLTZ()というストアドファンクションを作成した。
rfc822形式の日時文字列をOracle10g の Timestamp with local time zone型に変換するストアドファンクションである。

尚、rfc822のタイムゾーンとして、

     zone        =  "UT"  / "GMT"

/ "EST" / "EDT"
/ "CST" / "CDT"
/ "MST" / "MDT"
/ "PST" / "PDT"
/ 1ALPHA

/ ( ("+" / "-") 4DIGIT )

と規定されているが、"UT"及び、夏時間(*DT)、英字1文字以外についてのみ実装した。(Oracle10gのto_timestamp_tz()関数で指定できるタイムゾーンリージョン "GMT"/"EST"/"CST"/"MST"/"PST" だけに対応した。"UT"、夏時間、英字1文字、または、上記、以外のタイムゾーンが設定されているような状況があれば、その時に考えることに。ちなみに、私が購読しているblogのfeedでは、"GMT"しか利用されていないのも理由の一つである。)

Oracle10gで指定できるタイムゾーンリージョンは以下のようにして確認できる。詳細は、「マニュアル「Oracle10 database SQLクイック・リファレンス 10g」を参照のこと

SYS> select
2 unique tzname
3 from
4 v$timezone_names
5 where
6 tzname in (
7 'UT','GMT','EST','EDT','CST','CDT','MST','MDT','PST','PDT'
8 )
9 or length(tzname)=1;


TZNAME
----------------------------------------------------------------
CST
EST
GMT
MST
PST

SYS>

今日はここまで。次回は、上記仕様で作成したストアドファンクションのテスト及び、ソースを載せる予定。


2006/10/8追記。
SQLリファレンスの夏時間に関する記述を見ると、OracleのTimestamp with time zone型に関して、タイムゾーンリージョンを指定すると夏時間を考慮した変換がなされるとある。
聞いている曲:うん〜〜〜 iTunesで聞いているのは、Internet Radioなので、曲紹介はなし。       ちなみに、聞いているInternet Radioは、 SmoothJazz.com

| | コメント (0) | トラックバック (0)

2006年10月 6日 (金)

Mac De PL/SQL RSS Reader #10

FEEDフォーマットの判定テストの結果。これで、FEEDフォーマットの判定はできるようになった。

URL:http://megawatt.blogdns.net/blog/rdf91_xml
FEEDフォーマット:RSS version = 0.91

URL:http://technology.amis.nl/blog/?feed=rss
FEEDフォーマット:RSS version = 0.92

URL:http://megawatt.blogdns.net/blog/rdf10_xml
FEEDフォーマット:RDF version =

URL:http://miwa2006.exblog.jp/index.xml
FEEDフォーマット:RSS version = 2.0

URL:http://atsu-log.way-nifty.com/today_s_menu/atom.xml
FEEDフォーマット:ATOM version = 0.3

URL:http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/atom.xml
FEEDフォーマット:ATOM version =

今回のテストで使ったソースコードは以下。

CREATE OR REPLACE PROCEDURE RSS_FEED_READER_TEST
(
i_url IN VARCHAR2
)
AS
--============ TYPEs/VARIABLEs ===============================================
C_RSS CONSTANT VARCHAR2(7) := 'rss';
C_RDF CONSTANT VARCHAR2(7) := 'rdf:RDF';
C_ATOM CONSTANT VARCHAR2(7) := 'feed';
C_ATTR_NAME_VERSION CONSTANT VARCHAR2(7) := 'version';

v_url VARCHAR2(1024);

v_myParser DBMS_XMLPARSER.Parser;
v_rssDoc DBMS_XMLDOM.DomDocument;
v_itemNode DBMS_XMLDOM.DomNode;
v_childnode DBMS_XMLDOM.DomNode;
v_rssEntryList DBMS_XMLDOM.DomNodeList;
v_rssItemFields DBMS_XMLDOM.DomNodeList;
v_attrNamedNodeMap DBMS_XMLDOM.DomNamedNodeMap;
v_childNodeText VARCHAR2(32767);

-- FEEDのフォーマット(RSS/RDF/ATOM)を判別するためのルート要素のタグ名
v_rootElementTagName VARCHAR2(10);
-- RSS/RDF/ATOMのversion
v_version VARCHAR2(10);

-- for UTL_HTTP
v_req UTL_HTTP.REQ;
v_resp UTL_HTTP.RESP;

-- HTTP経由でRSS/ATOMソースを取り込むためのワーク
v_source VARCHAR2(1024);
v_tempSourceClob CLOB := NULL;

--
BEGIN
DBMS_OUTPUT.ENABLE(200000);
v_url := i_url;

-- FEEDを取得し、一時CLOBへ書き出す。(URL指定パースでの文字化け回避策)
v_req := UTL_HTTP.BEGIN_REQUEST(v_url);
UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
v_resp := UTL_HTTP.GET_RESPONSE(v_req);

DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_resp, v_source, true);
v_source := v_source || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_resp);
END;

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);

v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
v_rootElementTagName :=
DBMS_XMLDOM.GETTAGNAME
(
DBMS_XMLDOM.GETDOCUMENTELEMENT(v_rssDoc)
);
v_version :=
DBMS_XMLDOM.GETVALUE
(
DBMS_XMLDOM.GETATTRIBUTENODE
(
DBMS_XMLDOM.GETDOCUMENTELEMENT(v_rssDoc),
C_ATTR_NAME_VERSION
)
);

DBMS_OUTPUT.PUT_LINE('URL:' || i_url);
CASE v_rootElementTagName
WHEN c_atom THEN
DBMS_OUTPUT.PUT_LINE('FEEDフォーマット:ATOM' || ' version = ' || v_version);
WHEN c_rss THEN
DBMS_OUTPUT.PUT_LINE('FEEDフォーマット:RSS ' || ' version = ' || v_version);
WHEN c_rdf THEN
DBMS_OUTPUT.PUT_LINE('FEEDフォーマット:RDF ' || ' version = ' || v_version);
ELSE
RAISE_APPLICATION_ERROR(-20000,'ありえねぇー');
END CASE;

DBMS_LOB.FREETEMPORARY(v_tempSourceClob);
DBMS_XMLPARSER.FREEPARSER(v_myParser);

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(sqlerrm());
IF v_tempSourceClob IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_tempSourceClob);
END IF;
DBMS_XMLPARSER.FREEPARSER(v_myParser);
RAISE;

END RSS_FEED_READER_TEST;


聞いている曲:
Gary NumanのDance。当時、JapanのメンバーであったMick Karn をフィーチャーしたアルバム。1981年リリース。Gentlemen Take PolaroidsをイメージさせるMick Karnのサックスとフレットレスベースが気持ちいい。 Gary Numanの声は好き嫌いがハッキリとでると思うけど。。。

Gary Numan - Dance Gary Numan - Dance - She's Got Claws
Gary Numan - Dance - She's Got Claws

| | コメント (0) | トラックバック (0)

2006年10月 4日 (水)

Mac De PL/SQL RSS Reader #9

前回の続き。

feedフォーマットは、RSS 0.91, 0.92, 2.0と、RSS 0.9, 1.0 それに、ATOM 0.3, 1.0があるが、それらを区別するにはどうするのがいいのか?

各フォーマット共通の要素があり、属性として、フォーマット名とバージョンの文字列が取得できるようになっていれば話は簡単なのだが、そのような要素は存在しない。

ということで、やはり、素直に、各feedのルート要素名で区別するのが無難か? と思うようになる。。。

・<rss>ならば、
 Rich Site Summary(RSS 0.9x)とReally Simple Syndication(RSS 2.0)

・<rdf:RDF>ならば
 RDF Site Summary(RSS 0.9とRSS 1.0)

・<feed>ならば
 Atom Syndication Format (ちなみに、私が購読しているBlogには、version = 0.3 と 1.0のサイトがある)

さらに、細かな区別が必要であれば、各要素のversion属性値でより細かな区別を行う。

という手順を踏めば、なんとかなる、かな。。。


ちなみに、XSLT(PL/SQLだとDBMS_XSLPROCESSORパッケージを利用する)で変換する方法もあるが、今後のお楽しみのために残しておき、今回は、DBMS_XMLDOMパッケージ利用し、DOMプログラミングだけで作ろうと考えている。尚、一から作るのではなく、以前作成したRSS 0.91に対応したものを改造し、複数のfeedフォーマットに対応させる予定。


聞いている曲:DVDのほうがいいけどね。。

今年で、18周年を迎える、Blue Note Tokyo。送られてきた案内を見ると、、おや、6年降りの登場なんですね、NIACIN。
しかも、10/22の1日限り。慌てて、予約状況を見るも。。。。すでに満席。残念!!!

ということで、昔のアルバムでも。。。あれ〜、iTMSには、NIACINは無いのね! これまた残念といことで、Amazonにリンク張りま〜す。
BILLY SHEEHAN

 

| | コメント (0) | トラックバック (0)

2006年10月 3日 (火)

Mac De PL/SQL RSS Reader #8

Mac De PL/SQL RSS Reader #7の続き

さて、SafariのFeed Reader機能だけで配信される記事を読んでいる場合には全く意識していないのだが、いざ、自作となると面倒だと感じるところがある。 
その一つは、やはり、feedフォーマットが複数ある点だろうか。しかもそのフォーマット毎に複数のバージョンが存在する。

二つ目は、日付、時刻のフォーマット。rfc822または、rfc3339のいずれか利用されている点だ。

各feedのspecを斜め読みし、記事の公開日に対応する要素について調べてみると、

RSS 0.91のpubDate要素はrfc822
 但し、pubDate要素は、option要素なので存在しない場合もある。

RSS 1.0dc:date要素は、rfc3339

RSS 0.92 and 2.0pubDate要素も、rfc822
 但し、pubDate要素は、option要素なので存在しない場合もある。
 また、pubDate要素を利用せず、dc:date要素で拡張している場合もあようで、形式は、rfc3339となる。

ATOMのpublished要素は、rfc3339。参照、rfc4287 3.3 Date Constructs


私が作ろうとしているRSS Feed Readerは、ブログタイトル、記事のタイトルとURL、それに公開日時だけという単純ものなのだが、いろいろと調べなければならない。。。
間違いなく忘れそうなので備忘録として残しておく。。調べるだけでも疲れる。。。。。。


2006/10/4 追記、ATOM version="0.3"を使っている場合には、published要素ではなく、issued要素が利用され、rfc3339準拠。 ほんとに面倒ね。
David Sanbornは、今年の暮れも Blue Note Tokyoに来るようですね。

聞いている曲:
宇多田ヒカル - First Love (Featuring David Sanborn) 宇多田ヒカル & David Sanborn - First Love - EP - First Love (Featuring David Sanborn)
宇多田ヒカル & David Sanborn - First Love - EP - First Love (Featuring David Sanborn)

David Sanborn - Closer David Sanborn - Closer - Enchantment
David Sanborn - Closer - Enchantment

| | コメント (0) | トラックバック (0)

2006年9月28日 (木)

Mac De PL/SQL RSS Reader #7

さて、RSS ReaderをネタにDBMS_XMLDOMパッケージなどでも遊ぼうとしていたら、こんなの見つけた。


Oracle10g R1/R2の PL/SQL Package and Type ReferenceマニュアルによればDBMS_XMLDOM.HASATTRIBUTEファンクションの戻り値は、VARCHAR2となっている。(以下、マニュアルより抜粋)
HASATTRIBUTE Functions


DBMS_XMLDOM.HASATTRIBUTE(
elem IN DOMELEMENT,
name IN VARCHAR2)
RETURN VARCHAR2;

DBMS_XMLDOM.HASATTRIBUTE(
elem IN DOMELEMENT,
name IN VARCHAR2,
ns IN VARCHAR2)
RETURN VARCHAR2;


しかし、実際には、

SYS> spo xmldom_desc.log
SYS> desc dbms_xmldom

中略

SYS> spo off
SYS> !cat xmldom_desc.log | grep HASATTRIBUTE
FUNCTION HASATTRIBUTE RETURNS BOOLEAN
FUNCTION HASATTRIBUTE RETURNS BOOLEAN
FUNCTION HASATTRIBUTES RETURNS BOOLEAN
SYS>

ということで、DBMS_XMLDOM.HASATTRIBUTEファンクションの戻り値は、 BOOLEAN なので注意するべし。

さらに、DBMS_XMLDOM.HASATTRIBUTE()を使ってみると、Oracle10g 10.1.0.3.0, 10.2.0.2.0、それぞれで試してみたが、常に FALSE が返される。

ちなみに、DBMS_XMLDOM.GETATTRIBUTENODE()では、指定した属性ノードが正しく取り出せた。こちらが使えるので、とりあえず、なんとかなるか。。。

今後仕事で使う際には要注意なので、備忘録として記録しておく。(そのうちファンクションの問題共々、修正されるとは思うが。。。。)



聞いている曲:Japan - Gentoemen Take Polaroids - Taking Islands in Africa Japan - Gentlemen Take Polaroids - Taking Islands In Africa
Japan - Gentlemen Take Polaroids - Taking Islands In Africa

| | コメント (0) | トラックバック (0)

2006年8月14日 (月)

Mac De PL/SQL RSS Reader #6

つづきです。
PL/SQLで日本語対応RSS Readerが作れる事が確認できたので HTMLDB 2.0 に組み込み確認する。

Oracle HTMLDB 2.0で PL/SQL RSS Reader作成中のスナップショットをQuickTimeムービーにしました。
再生には、Apple QuickTimeプラグインが必要です。


サウンドトラックの無い、ファイルサイズ:2.3MB版のQuickTimeムービーはこちらから。



Apple iLifeのGarage Bandでサウンドトラックを付けたバージョン。ファイルサイズ:38MB版QuickTimeムービーはこちら。


聞いている曲:
David Bowie - TVC 15 David Bowie - Station to Station - TVC 15

| | コメント (0) | トラックバック (0)

2006年8月13日 (日)

Mac De PL/SQL RSS Reader #5

前回のつづきです。
当初のからmegawattさんのRSS 0.91フォーマットを対象にしているためその他のRSSフォーマットやATOMには対応していない。元ネタのようにXSLTスタイルシートを利用するのも良いだろう。
今回は、「元ネタの通りの方法で、日本語が文字化け無く処理できるのだろうか?」 という点を確認するということが目的であるため複数のRSSフォーマットに対応するつもりは無い。そのウチ試す予定だが。

ということで、最後に、今までほったらかしていた Oracle HTMLDB 2.0 を利用して RSS Reader を組み込んでみることにした。
Oracle HTMLDB 2.0については以前の記事を参考にして貰いたい。



HTMLDBに組み込んだコードはこれ。

DECLARE
TYPE rss_type IS RECORD
(
title VARCHAR2(2000),
link VARCHAR2(200)
);
v_rss_item rss_type;
v_rss_empty_item rss_type;

v_url VARCHAR2(32767)
:= 'http://megawatt.blogdns.net/blog/rdf91_xml';

v_myParser DBMS_XMLPARSER.Parser;
v_rssDoc DBMS_XMLDOM.DomDocument;
v_itemNode DBMS_XMLDOM.DomNode;
v_childnode DBMS_XMLDOM.DomNode;
v_rssEntryList DBMS_XMLDOM.DomNodeList;
v_rssItemFields DBMS_XMLDOM.DomNodeList;
v_childNodeText VARCHAR2(32767);

v_req UTL_HTTP.REQ;
v_resp UTL_HTTP.RESP;

v_source VARCHAR2(1024);
v_tempSourceClob CLOB;
v_tempXMLTYPE XMLTYPE;


PROCEDURE report_rss_item(p_rss_item IN rss_type)
IS
BEGIN
HTP.TABLEROWOPEN();
HTP.TABLEDATA(
'<a href="'
|| p_rss_item.link
|| '" style="color:#FF0000" target="_blank">'
|| p_rss_item.title
|| '</a>'
);
HTP.TABLEROWCLOSE();

EXCEPTION
WHEN OTHERS THEN
HTP.PRINT('Error occured in report_rss_item internal procedure');
RAISE;
END report_rss_item;

--****************************************************************************
-- Main procedure
--****************************************************************************
BEGIN
v_req := UTL_HTTP.BEGIN_REQUEST(v_url);
UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1');
UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
v_resp := UTL_HTTP.GET_RESPONSE(v_req);

DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_resp, v_source, true);

-- 改行コード強制的に付加。
-- xml_println()でDBMS_OUTPUT.PUT_LINE()が、最大255文字までしか
-- 表示できないことへの一時的な対策。(試しているサイトについてはこれで
-- 回避できているので今のところはこのままで。)
v_source := v_source || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);

END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_resp);
END;

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
v_tempXMLType := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
v_rssEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(v_rssDoc, 'item');
v_rss_item := v_rss_empty_item;

HTP.TABLEOPEN();
HTP.TABLEROWOPEN();
HTP.TABLEHEADER(
cvalue => v_tempXMLType.EXTRACT('/rss/channel/title/text()').GETSTRINGVAL
|| ' - most recent '
|| DBMS_XMLDOM.GETLENGTH(v_rssEntryList)
|| ' articles:',
cattributes => 'style="font-size:18px"',
calign => 'align="left"'
);
HTP.TABLEROWCLOSE();

FOR i IN 1..DBMS_XMLDOM.GETLENGTH(v_rssEntryList) LOOP
v_itemNode := DBMS_XMLDOM.ITEM(v_rssEntryList, i-1);
v_rssItemFields := DBMS_XMLDOM.GETCHILDNODES(v_itemNode);

FOR j IN 1..DBMS_XMLDOM.GETLENGTH(v_rssItemFields) LOOP
v_childnode := DBMS_XMLDOM.ITEM(v_rssItemFields, j-1);
v_childNodeText := DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETFIRSTCHILD(v_childnode)
);

CASE DBMS_XMLDOM.GETNODENAME(v_childnode)
WHEN 'title' THEN
v_rss_item.title := v_childNodeText;

WHEN 'link' THEN
v_rss_item.link := v_childNodeText;

ELSE
NULL;
END CASE;
END LOOP;
report_rss_item(v_rss_item);
END LOOP;

HTP.TABLECLOSE();
DBMS_LOB.FREETEMPORARY(v_tempSourceClob);
DBMS_XMLPARSER.FREEPARSER(v_myParser);

EXCEPTION
WHEN OTHERS THEN
HTP.PRINT(
'Main Procedure:'
|| sqlerrm()
);
RAISE;
END;



前回のストアドプロシージャのロジックとの違いはあまり無いが、無名PL/SQLブロックとして組み込むことと、DBMS_OUTPUTパッケージを利用している部分を、HTPパッケージを利用するように変更しなければならない。(やっつけ仕事的なコードになってしまったなが、文字化け回避の方法が見えればOKなので他には目をつぶってくださいませ。。。)

尚、
HTPパッケージについては、PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス
HTMLDB 2.0についてはOracle HTMLDB 2.0(英語)や、HTMLDB 2.0のオンラインヘルプなどが参考になるだろう。
#今回は、オンラインヘルプしか利用ませんでした。そんな程度でも作れるくらい簡単です。。。


次回は、HTMLDB 2.0 に前述の無名PL/SQLブロックを組み込んで試すことにする。




これから見ようとしているDVD:
随分前、こんな記事を書いたが、なんと ザ・インターネット2がリリースされていた。
邦題:インターネットの続編?のようなのだが。。。。不覚にも全くしらなかった。でも主演はサンドラブロックではなさそうだな。。。そういえば、ザ・インターネットが公開されたのは1996年。10年も経ったのか・・・と。


ところで、インターネット2っていうと、次世代インターネットを指していたりする。


##############################
2006/08/13
ザ・インターネット2見ましたが、ぜんぜん面白くない。ザ・インターネットの続編だなんて、とんでもない無いですね。
ザ・インターネットの延長線上にあると思ってみてしまうとがっかりするので、完全に別ものと思って見てくださいね。

| | コメント (0) | トラックバック (0)

2006年8月 9日 (水)

Mac De PL/SQL RSS Reader #4

前回のつづきです。
前回までで文字化けを回避できることが確認できたので、本題RSSリーダーの元ネタで試してみることにする。
尚、オリジナルになるべく近い形にしてある。(対象は、megawattさんRSS 0.91フォーマット)

まずは、結果から。(いつものように、Oracle SQL Developer 1.0 for MacOSXを使ってます)
Sqldevok



データベースOracle10g R1 grasscatfishに接続中です。
begin...
====================
メガ放談 - most recent 15 articles:
====================
TITLE: ギザ耳は地域猫の証し
URL : http://megawatt.blogdns.net/blog/254
—————————————-

TITLE: 亀田家親子夏休み日記
URL : http://megawatt.blogdns.net/blog/253
—————————————-

TITLE: 社会保険事務所に行ってきた
URL : http://megawatt.blogdns.net/blog/252
—————————————-

TITLE: 重なるときは重なる Part2
URL : http://megawatt.blogdns.net/blog/251
—————————————-

TITLE: 重なるときは重なる
URL : http://megawatt.blogdns.net/blog/250
—————————————-

TITLE: うしろすがた
URL : http://megawatt.blogdns.net/blog/249
—————————————-

TITLE: 猫のための写真講座/2006年度前期・4
URL : http://megawatt.blogdns.net/blog/248
—————————————-

TITLE: ワイン100mlが80キロカロリー!!
URL : http://megawatt.blogdns.net/blog/247
—————————————-

TITLE: はっちゃんではないはっちゃん
URL : http://megawatt.blogdns.net/blog/246
—————————————-

TITLE: ちょっと、走ってる
URL : http://megawatt.blogdns.net/blog/245
—————————————-

TITLE: 命名、じみへん
URL : http://megawatt.blogdns.net/blog/244
—————————————-

TITLE: 猫まんが at門前仲町
URL : http://megawatt.blogdns.net/blog/243
—————————————-

TITLE: 猫を拾った日
URL : http://megawatt.blogdns.net/blog/242
—————————————-

TITLE: お飲物なににしますか?
URL : http://megawatt.blogdns.net/blog/241
—————————————-

TITLE: 門前仲町・深川不動堂
URL : http://megawatt.blogdns.net/blog/240
—————————————-

...End
プロセス終了。
データベースOracle10g R1 glasscatfishから切断中です。

以下、プロシージャのソース。
比較し易いように、オリジナルのソースになるべく近い形式にしてある。

CREATE OR REPLACE PROCEDURE RSS_FEED_READER
(
i_url IN VARCHAR2
)
AS
--============ TYPEs/VARIABLEs ===============================================
TYPE rss_type IS RECORD
(
title VARCHAR2(2000),
link VARCHAR2(200),
pubDate VARCHAR2(200),
category VARCHAR2(500),
description VARCHAR2(4000)
);
v_rss_item rss_type;
v_rss_empty_item rss_type; -- v_rss_item初期化用

v_url VARCHAR2(32767);

-- XML PARSER
v_myParser DBMS_XMLPARSER.Parser;

-- RSSまたは、ATOMフォーマットのDOM
v_rssDoc DBMS_XMLDOM.DomDocument;

v_itemNode DBMS_XMLDOM.DomNode;
v_childnode DBMS_XMLDOM.DomNode;
v_rssEntryList DBMS_XMLDOM.DomNodeList;
v_rssItemFields DBMS_XMLDOM.DomNodeList;
v_childNodeText VARCHAR2(32767);

-- for UTL_HTTP
v_req UTL_HTTP.REQ;
v_resp UTL_HTTP.RESP;
-- HTTP経由でRSS/ATOMソースを取り込むためのワーク
v_source VARCHAR2(1024);
v_tempSourceClob CLOB;

-- RSS/ATOMをXMLTYPEで扱うためのワーク
v_tempXMLTYPE XMLTYPE;

--========== Internal PROCEDUREs/FUNCTIONs ===================================
--
--****************************************************************************
--* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ
--*
--* NOTE:
--* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限がないため、
--* 255文字毎に分割出力する必要はなくなる
--****************************************************************************
PROCEDURE println
(
i_text IN VARCHAR2
)
IS
v_src VARCHAR2(32767);
v_tempStr VARCHAR2(32767);
BEGIN
v_src := i_text;
IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
ELSE
v_tempStr := v_src;
END IF;

WHILE v_tempStr IS NOT NULL LOOP
IF LENGTH(v_tempStr)> 255 THEN
FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255));
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE(v_tempStr);
END IF;

IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
ELSE
EXIT;
END IF;
END LOOP;

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error Occured : println(VARCHAR2) internal procedure.');
DBMS_OUTPUT.PUT_LINE(sqlerrm());
RAISE;
END println;


PROCEDURE report_rss_item(p_rss_item IN rss_type)
IS
BEGIN
println('TITLE: '||p_rss_item.title);
println('URL : '||p_rss_item.link);

IF p_rss_item.pubDate IS NOT NULL THEN
println('Published on: '||p_rss_item.pubDate);
END IF;

IF p_rss_item.category IS NOT NULL THEN
println('Category: '||p_rss_item.category);
END IF;

IF p_rss_item.description IS NOT NULL THEN
println('==');
println('Summary: '||p_rss_item.description);
END IF;

println('—————————————-');
println(' ');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error occured : report_rss_item internal procedure');
DBMS_OUTPUT.PUT_LINE(sqlerrm());
RAISE;
END report_rss_item;

--****************************************************************************
--* Main procedure
--****************************************************************************
BEGIN
DBMS_OUTPUT.ENABLE(200000);
println('begin...');

v_url := i_url;
IF v_url IS NULL THEN
RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。');
END IF;

v_req := UTL_HTTP.BEGIN_REQUEST(v_url);
UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1');
UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
v_resp := UTL_HTTP.GET_RESPONSE(v_req);

-- RSSソースを一時CLOBへ書き出す
DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_resp, v_source, true);

-- 改行コード強制的に付加。
-- xml_println()でDBMS_OUTPUT.PUT_LINE()が、最大255文字までしか
-- 表示できないことへの一時的な対策。(試しているサイトについてはこれで
-- 回避できているので今のところはこのままで。)
v_source := v_source || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_resp);
END;

println('====================');
v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
v_tempXMLType := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
v_rssEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(v_rssDoc, 'item');
v_rss_item := v_rss_empty_item;

println
(
v_tempXMLType.EXTRACT('/rss/channel/title/text()').GETSTRINGVAL
|| ' - most recent '
|| DBMS_XMLDOM.GETLENGTH(v_rssEntryList)
|| ' articles:'
);
println('====================');

FOR i IN 1..DBMS_XMLDOM.GETLENGTH(v_rssEntryList) LOOP
v_itemNode := DBMS_XMLDOM.ITEM(v_rssEntryList, i-1);
v_rssItemFields := DBMS_XMLDOM.GETCHILDNODES(v_itemNode);

FOR j IN 1..DBMS_XMLDOM.GETLENGTH(v_rssItemFields) LOOP
v_childnode := DBMS_XMLDOM.ITEM(v_rssItemFields, j-1);
v_childNodeText := DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETFIRSTCHILD(v_childnode)
);

CASE DBMS_XMLDOM.GETNODENAME(v_childnode)
WHEN 'title' THEN
v_rss_item.title := v_childNodeText;

WHEN 'link' THEN
v_rss_item.link := v_childNodeText;

WHEN 'published' THEN
v_rss_item.pubDate := v_childNodeText;

WHEN 'category' THEN
v_rss_item.category := v_childNodeText;

WHEN 'description' THEN
v_rss_item.description := v_childNodeText;

ELSE
NULL;
END CASE;
END LOOP;

report_rss_item(v_rss_item);
END LOOP;

DBMS_LOB.FREETEMPORARY(v_tempSourceClob);
DBMS_XMLPARSER.FREEPARSER(v_myParser);

println('...End');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Main Procedure:'
|| sqlerrm()
);
RAISE;

END RSS_FEED_READER;


今聞いている曲:
これらの曲がリリースされた時期から随分経っているが、種々の問題は残されたままのような気がする。と考えつつ。。。

ALCATRAZZ -- Hiroshima mon amour

Human Leage - The LebanonThe Human League - Hysteria - The Lebanon
The Human League - Hysteria - The Lebanon

| | コメント (0) | トラックバック (0)

2006年8月 8日 (火)

Mac De PL/SQL RSS Reader #3

前回のつづきです。
さて、文字化けを回避する方法はないかと考えてみた。
URL指定で、Oracle10g R1のDBMS_XMLPARSERパッケージのパーサーでパースする場合、裏で行われて言うHTTPで正しくエンコーディングされていないのが原因でだろうと考え、試しにUTL_HTTPパッケージを使いRSSソースを取得してみることにした。

尚、DBMS_XMLPARDERパッケージ、DBMS_XMLDOMパッケージ、UTL_HTTPパッケージ、UTL_TCPパッケージの詳細については、「PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス」を参照のこと。

まずは、結果から。
以下のように、HTTPで取得したRSSを表示すると文字化けは発生しなかった。(思った通り!)

データベースOracle10g R1 glasscatfishに接続中です。<br>
begin...
====================
DBMS_XMLPARSERバージョン:10.1.0.2.0
DBMS_XMLDOMバージョン   :

<rss version="0.91">
  <channel>
    <title>メガ放談</title>
    <link>http://megawatt.blogdns.net/blog</link>
    <description>A Weblog Product for Zope</description>
    <item>
      <title>亀田家親子夏休み日記</title>
      <link>http://megawatt.blogdns.net/blog/253</link>
    </item>
    <item>
      <title>社会保険事務所に行ってきた</title>
      <link>http://megawatt.blogdns.net/blog/252</link>
    </item>
    <item>
      <title>重なるときは重なる Part2</title>
      <link>http://megawatt.blogdns.net/blog/251</link>
    </item>
    <item>
      <title>重なるときは重なる</title>
      <link>http://megawatt.blogdns.net/blog/250</link>
    </item>
    <item>
      <title>うしろすがた</title>
      <link>http://megawatt.blogdns.net/blog/249</link>
    </item>
    <item>
      <title>猫のための写真講座/2006年度前期・4</title>
      <link>http://megawatt.blogdns.net/blog/248</link>
    </item>
    <item>
      <title>ワイン100mlが80キロカロリー!!</title>
      <link>http://megawatt.blogdns.net/blog/247</link>
    </item>
    <item>
      <title>はっちゃんではないはっちゃん</title>
      <link>http://megawatt.blogdns.net/blog/246</link>
    </item>
    <item>
      <title>ちょっと、走ってる</title>
      <link>http://megawatt.blogdns.net/blog/245</link>
    </item>
    <item>
      <title>命名、じみへん</title>
      <link>http://megawatt.blogdns.net/blog/244</link>
    </item>
    <item>
      <title>猫まんが at門前仲町</title>
      <link>http://megawatt.blogdns.net/blog/243</link>
    </item>
    <item>
      <title>猫を拾った日</title>
      <link>http://megawatt.blogdns.net/blog/242</link>
    </item>
    <item>
      <title>お飲物なににしますか?</title>
      <link>http://megawatt.blogdns.net/blog/241</link>
    </item>
    <item>
      <title>門前仲町・深川不動堂</title>
      <link>http://megawatt.blogdns.net/blog/240</link>
    </item>
    <item>
      <title>う〜ん、まずい。</title>
      <link>http://megawatt.blogdns.net/blog/239</link>
    </item>
    <item>
      <title>短歌熱</title>
      <link>http://megawatt.blogdns.net/blog/238</link>
    </item>
  </channel>
</rss>
====================

...End
プロセス終了。<br>
データベースOracle10g R1 glasscatfishから切断中です。<br>

以下、変更後のプロシージャのソースを示す。
変更点は、
DBMS_XMLPARSERパッケージのパーサーで、URL直指定でパースするのではなく、HTTP経由でCLOBにRSSソースを取り込み、CLOBをパースするようにした。
XMLをプリントする内部プロシージャも変更し、println(CLOB)からxml_println(XMLTYPE)へ変更した。(XMLTYPEにしておいたほうがなにかと便利なので。尚、元ネタは、ここ) 

CREATE OR REPLACE PROCEDURE RSS_FEED_READER
(
  i_url IN VARCHAR2
)
AS
  --============ TYPEs/VARIABLEs ===============================================
  TYPE rss_type IS RECORD
  (
    title       VARCHAR2(2000),
    link        VARCHAR2(200),
    pubDate     VARCHAR2(200),
    category    VARCHAR2(500),
    description VARCHAR2(4000)
  );
  v_rss_item        rss_type;
  v_rss_empty_item  rss_type; -- v_rss_item初期化用

  v_url             VARCHAR2(32767);

 
    -- XML PARSER
  v_myParser        DBMS_XMLPARSER.Parser;

  -- RSSまたは、ATOMフォーマットのDOM
  v_rssDoc          DBMS_XMLDOM.DomDocument; 

    -- for UTL_HTTP
  v_req             UTL_HTTP.REQ;
  v_resp            UTL_HTTP.RESP;

  -- HTTP経由でRSS/ATOMソースを取り込むためのワーク
  v_source          VARCHAR2(1024);
  v_tempSourceClob  CLOB;
         
   --========== Internal PROCEDUREs/FUNCTIONs ===================================
  --
  --****************************************************************************
  --* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ
  --*
  --* NOTE:
  --* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限が緩和され32767文字まで出力できるようになるためがないため
  --* 255文字毎に分割出力する必要はなくなるなぁ。
  --****************************************************************************
  PROCEDURE println
  (
    i_text IN VARCHAR2
  )
  IS
    v_src     VARCHAR2(32767);
    v_tempStr VARCHAR2(32767);
  BEGIN
    v_src := i_text;
    IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
      v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
      v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
    ELSE
      v_tempStr := v_src;
    END IF;
   
    WHILE v_tempStr IS NOT NULL LOOP
      IF LENGTH(v_tempStr)> 255 THEN
        FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP
          DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255));
        END LOOP;
      ELSE
        DBMS_OUTPUT.PUT_LINE(v_tempStr);
      END IF;

      IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
        v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
        v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
      ELSE
        EXIT;
      END IF;
    END LOOP;
   
  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Error Occured : println(VARCHAR2) internal procedure.');
      DBMS_OUTPUT.PUT_LINE(sqlerrm());
      RAISE;
  END println;

  --****************************************************************************
  --* XMLTYPEに格納されたXMLソースをプリントする。
  --* (Oracle10g R1だと、255文字毎の分割プリントは必要かも。。。未実装)
  --*
  --* NOTE:
  --* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限がないため、
  --* 255文字毎に分割出力する必要はなくなる32767文字毎の分割出力でもOK.
  --****************************************************************************
  PROCEDURE xml_println
  (
    i_text IN XMLTYPE
  )
  IS
    v_str LONG;
  BEGIN
    v_str := i_text.EXTRACT('/*').GETSTRINGVAL();
    WHILE(v_str IS NOT NULL) LOOP
      DBMS_OUTPUT.PUB_LINE(SUBSTR(v_str, 1, INSTR(v_str, CHR(10)) - 1));
      v_str := SUBSTR(v_str, INSTR(v_str, CHR(10)) + 1);
    END LOOP;

  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Error Occured : xml_println(XMLTYPE) internal procedure.');
      DBMS_OUTPUT.PUT_LINE(sqlerrm());
      RAISE;
  END xml_println;

--****************************************************************************
--* Main Procedure
--****************************************************************************
BEGIN
  DBMS_OUTPUT.ENABLE(200000);
  println('begin...');

  v_url := i_url;
  IF v_url IS NULL THEN
    RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。');
  END IF;

  v_req := UTL_HTTP.BEGIN_REQUEST(v_url);
  UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1');
  UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
  v_resp := UTL_HTTP.GET_RESPONSE(v_req);
 
  -- RSSソースを一時CLOBへ書き出す
  DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
  BEGIN
    LOOP
      UTL_HTTP.READ_LINE(v_resp, v_source, true);
      
      -- 改行コード強制的に付加。
      -- xml_println()でDBMS_OUTPUT.PUT_LINE()が、最大255文字までしか
      -- 表示できないことへの一時的な対策。(試しているサイトについてはこれで
      -- 回避できているので今のところはこのままで。)
      v_source := v_source || UTL_TCP.CRLF;
      DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
    END LOOP;
  EXCEPTION
    WHEN UTL_HTTP.END_OF_BODY THEN
      UTL_HTTP.END_RESPONSE(v_resp);
  END;
 
  println('====================');
  v_myParser := DBMS_XMLPARSER.NEWPARSER();
  DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
  v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
 
  println('DBMS_XMLPARSERバージョン:'||DBMS_XMLPARSER.GETRELEASEVERSION());
  println('DBMS_XMLDOMバージョン   :'||DBMS_XMLDOM.GETVERSION(v_rssDoc));
  println(' ');
  xml_println(DBMS_XMLDOM.GETXMLTYPE(v_rssDoc));
  println('====================');
  println(' ');
  DBMS_LOB.FREETEMPORARY(v_tempSourceClob);
  DBMS_XMLPARSER.FREEPARSER(v_myParser);

  println('...End');

EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Error Occured : main procedure.');
    DBMS_OUTPUT.PUT_LINE(sqlerrm());
    RAISE;

    END RSS_FEED_READER;

また、前述のようにした事で、Mac De Oracleなどで発生してたココログのATOM配信フォーマットのパースエラーも消えた!?(やはり文字化けが影響していたようだ。)
以下に、Mac De OracleのATOMを読み込んだOracle SQL Developer 1.0 for MacOSXのスナップショットを示す。


Jdevok

Oracle10g R1で、なんとか日本語対応のRSS Readerを作ることもできそうな感触。。。。Oracle10g R2は、MacOSX版がリリースされていないの(本当にリリースされるのか??)で、それまではLinux版のOracel10g R2で試してみるか。。。

今聞いている曲:
Malene Mortensen - Date with a DreamMalene Mortensen - デイト・ウィズ・ア・ドリーム GENAI - HAEVEN OF EARTHジェナイ - ヘブン・オン・アース

| | コメント (0) | トラックバック (0)

2006年8月 7日 (月)

Mac De PL/SQL RSS Reader #2

前回のつづきです。

前回、


RSS Readerの実験に利用するBlogは、私の友人であるmegawattさんのサイトを利用させて頂いた。(自分のブログである、Mac De OracleのRSSを利用していないのだが、理由は後日!)

と書いたが、当初、私のブログ(Mac De Oracle)で試そうと思ったのだが、何故、利用しなかったのか書いておく。
ココログは、RSSフォーマットではなく、Atom配信フォーマット。これはXMLのフォーマットが異なるだけなので、利用しなかった理由ではない。問題は、ココログのATOM配信フォーマットをDBMS_XMLPARSERパッケージのParserでパースすると、パースエラーが発生するためだ。

以下、前回のプロシージャを利用してMac De OracleのATOMを解析した実行結果を示す。(実行には、Oracle PL/SQL Developer 1.0を利用した。)

データベースOracle10g Scottに接続中です。
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 63
中にエラーが発生しました
ORA-06512: "SCOTT.RSS_FEED_READER", 行155
ORA-06512: 行6
begin...
Main Procedure:ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 63
中にエラーが発生しました
プロセス終了。
データベースOracle10g Scottから切断中です。

私のブログだけが問題なのか? 少々、心配になったので、私のお気に入りブログの一つである「鎌倉withLove」(現在は、ご自身で立ち上げたサイトに移行されているが、まだ、ココログにも残っているのでココログのATOMでも試させていただいた。)でも試してみた。やはり、同じエラーでXMLのパースエラーとなる。

Macdeoracleatom_error

新しい「鎌倉withLove」のサイトのATOMでも試してみたのだが、そちらではパースエラーは発生していない。文字化けは発生するが。。。(ココログもベースはMovableTypeだと思うのだが。。。随分カスタマイズされているようで。。)

Kamakurawithlove_ok

#尚、パースエラーの原因は、DBMS_XMLPARDERパッケージで行うURL直指定パースで発生する文字化けが絡んでいる可能性も捨てきれない。(これは後日確認する予定。)


今聞いている曲:
Najee - Tokyo Blue Kim Waters - All for Love

| | コメント (0) | トラックバック (0)

2006年8月 6日 (日)

Mac De PL/SQL RSS Reader #1

Mac De Oracle、久々の投稿です。前回までの騒ぎはなんとか収束。(あとはベンダーさん次第。。)

ということで、以前から読んでいるこのブログの記事にあるPL/SQLでRSS Reader!
そのネタの一部?!を試してみようと思う。まず、手始めに一番気になっているエンコーディングの部分から始めることにする。

環境は、 いつもの Oracle10g R1 EE for MacOSX Serverを利用する。(インストール方法などは、こちらを参考にしてください。
尚、MacOS Xは、以下のように現在の最新版を利用している。なお、データベースキャラクタセットは、JA16SJISTILDEである。

Os

RSS Readerの実験に利用するBlogは、私の友人であるmegawattさんのサイトを利用させて頂いた。(自分のブログである、Mac De OracleのRSSを利用していないのだが、理由は後日!)
megawattさんRSSのバージョンは、RSS 0.91RSS 1.0を提供しているが、当面はRSS 0.91で遊ぶことにする。

megawattさん、いろいろと試していたので、アクセスログがタップリ吐かれていると思いますが、DOS攻撃ではないのでご安心を! (^^;;;;;

さて、本題。
結果を先に書いておくと、Oracle10g R1のDBMS_XMLPARSERパッケージのXMLパーサーでRSS FeedのURLを直指定しパースした場合、マルチバイト文字は文字化した。(Oracle10g R2ではどうなのかは後日確認する予定)。 なんとかエンコーディングを指定できないものかと調べてみたが、Oracle10g R1のDBMS_XMLPARSERでは、XMLパーサーに対してエンコーディングを指定することはできないようだ。(マニュアルをざっと読んでみたが、該当するプロシージャもファンクションも存在しない。)


以下は、Oracle10g R1 EE for MacOSX ServerのDBMS_XMLPARSERパッケージを利用してパース後、XMLDOMからRSSソースを取り出しリストした結果である。文字の化け方から想像すると、UTF-8をISO Latin 1としてエンコードしているのかもしれない。
尚、すべての操作はOracle SQL Developer 1.0を利用して行った。(便利なのだがMacOSXだと、debuggerの動作がかなり遅いかも。。実際にはdebuggerを起動しなくても試せるので問題は無かったのだが。。)


_1 _2

_3 _4



データベースOracle10g R1 glasscatfishに接続中です。
begin...
DBMS_XMLPARSERバージョン:10.1.0.2.0
DBMS_XMLDOMバージョン :1.0
=== パース済みDOMから取得したRSSソース ===
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"
"http://my.netscape.com/publish/formats/rss-0.91.dtd">
<rss version="0.91">
<channel>
<title>a?!a?¬a??e≪?</title>
<link>http://megawatt.blogdns.net/blog</link>
<description>A Weblog Product for Zope</description>

<item>
<title>c??a??a??e?oao?a??a??a?≪e!?a?£a?|a??a??</title>
<link>http://megawatt.blogdns.net/blog/252</link>
</item>

<item>
<title>e??a?aa??a?¨a??a? ̄e??a?aa?? Part2</title>
<link>http://megawatt.blogdns.net/blog/251</link>
</item>

<item>
<title>e??a?aa??a?¨a??a? ̄e??a?aa??</title>
<link>http://megawatt.blogdns.net/blog/250</link>
</item>

<item>
<title>a??a??a??a??a??a??</title>
<link>http://megawatt.blogdns.net/blog/249</link>
</item>

<item>
<title>c?≪a?Ra??a??a?Ra??c??e¬?ao§i??2006a1´ao|a??a??a?≫i??</title>
<link>http://megawatt.blogdns.net/blog/248</link>
</item>

<item>
<title>a? ̄a??a?3100mla??80a?-a?-a?≪a?-a?aa??!!</title>
<link>http://megawatt.blogdns.net/blog/247</link>
</item>

<item>
<title>a? ̄a?£a?!a??a??a?§a? ̄a?aa??a? ̄a?£a?!a??a??</title>
<link>http://megawatt.blogdns.net/blog/246</link>
</item>


<item>
<title>a?!a??a?£a?¨a??eμ°a?£a?|a??</title>
<link>http://megawatt.blogdns.net/blog/245</link>
</item>

<item>
<title>a??a??a??a??a??a?,a??</title>
<link>http://megawatt.blogdns.net/blog/244</link>
</item>

<item>
<title>c?≪a??a??a?? ate??a??a≫2c?o</title>
<link>http://megawatt.blogdns.net/blog/243</link>
</item>

<item>
<title>c?≪a??a??a?£a??a?¥</title>
<link>http://megawatt.blogdns.net/blog/242</link>
</item>

<item>
<title>a??e£2c?ca?aa?≪a?≪a??a??a??a???</title>
<link>http://megawatt.blogdns.net/blog/241</link>
</item>

<item>
<title>e??a??a≫2c?oa?≫a・±a・?a,?a??a??</title>
<link>http://megawatt.blogdns.net/blog/240</link>
</item>

<item>
<title>a??a??a??a??a??a??a??a??</title>
<link>http://megawatt.blogdns.net/blog/239</link>
</item>

<item>
<title>c?-a-?c?±</title>
<link>http://megawatt.blogdns.net/blog/238</link>
</item>

<item>
<title>a??a??a??a??a??a??a?aa??a?§</title>
<link>http://megawatt.blogdns.net/blog/237</link>
</item>

</channel>
</rss>
====================
...End
プロセス終了。
データベースOracle10g R1 glasscatfishから切断中です。

以下は、AMIS Technology Blogのサンプルコードを参考にして作成したプロシージャのソースである。
URLで指定されたRSSソースをDBMS_XMLPARSERパッケージのXMLパーサーでパースし、生成されたXMLDOMオブジェクトからRSSソースをリストするしている。


CREATE OR REPLACE PROCEDURE RSS_FEED_READER
(
i_url IN VARCHAR2
)
AS
--============ TYPEs/VARIABLEs ===============================================
TYPE rss_type IS RECORD
(
title VARCHAR2(2000),
link VARCHAR2(200),
pubDate VARCHAR2(200),
category VARCHAR2(500),
description VARCHAR2(4000)
);
v_rss_item rss_type;
v_rss_empty_item rss_type; -- v_rss_item初期化用


v_url VARCHAR2(32767);

-- XML PARSER
v_myParser DBMS_XMLPARSER.Parser;

-- XMLDOM
v_rssDoc DBMS_XMLDOM.DomDocument;

-- for UTL_HTTP
v_req UTL_HTTP.REQ;
v_resp UTL_HTTP.RESP;
v_source VARCHAR2(1024);

-- RSSソース用CLOB(SYS.XMLTYPE型にしたほうがよかったかもしれないが、現時点ではCLOBで!)
v_tempClob CLOB;

--========== Internal PROCEDUREs/FUNCTIONs ===================================
--
--****************************************************************************
--* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ
--****************************************************************************
--
PROCEDURE println
(
i_text IN VARCHAR2
)
IS
v_src VARCHAR2(32767);
v_tempStr VARCHAR2(32767);
BEGIN
v_src := i_text;
IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
ELSE
v_tempStr := v_src;
END IF;

WHILE v_tempStr IS NOT NULL LOOP
IF LENGTH(v_tempStr)> 255 THEN
FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255));
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE(v_tempStr);
END IF;

IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
ELSE
EXIT;
END IF;
END LOOP;

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'println(VARCHAR2) internal procedure:'
|| sqlerrm()
);
RAISE;
END println;

--****************************************************************************
--* CLOBの文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ
--****************************************************************************
--
PROCEDURE println
(
i_text IN CLOB
)
IS
v_src CLOB;
v_tempStr CLOB;
BEGIN
v_src := i_text;
IF INSTR(v_src, UTL_TCP.CRLF) = 0 THEN
v_src := REPLACE(v_src, '><', '>'||UTL_TCP.CRLF||'<');
END IF;

v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := TRIM(LEADING UTL_TCP.CRLF FROM SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)));

WHILE v_tempStr IS NOT NULL LOOP
IF LENGTH(v_tempStr) > 255 THEN
FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255));
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE(v_tempStr);
END IF;
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := TRIM(LEADING UTL_TCP.CRLF FROM SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)));
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'println(CLOB) internal procedure:'
|| sqlerrm()
);
RAISE;
END println;

--****************************************************************************
--* Main Procedure
--****************************************************************************
BEGIN
DBMS_OUTPUT.ENABLE(200000);
println('begin...');


v_url := i_url;
IF v_url IS NULL THEN
RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。');
END IF;

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSE(v_myParser, v_url);
v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
DBMS_LOB.CREATETEMPORARY(v_tempClob, FALSE);
DBMS_XMLDOM.WRITETOCLOB(v_rssDoc, v_tempClob);
println('DBMS_XMLPARSERバージョン:'||DBMS_XMLPARSER.GETRELEASEVERSION());
println('DBMS_XMLDOMバージョン :'||DBMS_XMLDOM.GETVERSION(v_rssDoc));
println(' ');
println('=== パース済みDOMから取得したRSSソース ===');
println(v_tempClob);
println('====================');
println(' ');
DBMS_LOB.FREETEMPORARY(v_tempClob);

DBMS_XMLPARSER.FREEPARSER(v_myParser);

println('...End');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Main Procedure:'
|| sqlerrm()
);
RAISE;

END RSS_FEED_READER;


次回は、RSSをパースする際、RSS FEEDのURLを直指定したパースではなく、一旦、UTL_HTTPパッケージを利用してRSSを取得、CLOB変換する。そのCLOBをDBMS_XMLPARSERパッケージのパーサーでパースし、結果を確認してみることにする。
(ちなみに、WindowsのOracle10g R2 EEではXMLDOMが修正されたのか、DBMS_XMLPARSERパッケージかDBMS_XMLDOMパッケージが改良されたのか?。異なる結果をしてしている。それに関しては別記事にて書く予定)


今聞いている曲:
Dave Koz - Lucky Man Dave Koz - The Dance Richard Elliot - Metro Blue

| | コメント (0) | トラックバック (0)