会社から家まで歩いて帰ってみる その6 京急川崎→京急鶴見
まずは京急川崎の駅から銀柳街を抜ける。
普通に繁盛している商店街ではあるが近隣はパチンコ屋と飲み屋ばかりで騒々しい。
砂子のあたりからまた旧東海道に戻る。

このあたりの旧東海道は一応両脇に歩道が整備されているので歩きやすい。
京浜急行の線路沿いはチネチッタとかがあって割りと華やかなところが多いのだが
旧東海道はかなり地味な通りだ。

そのまままっすぐ進むと八丁畷の駅前の踏切に出る。
踏切ではどちらも車が結構繋がっていて、道路特定財源の投入が求められそうだ。
旧東海道を進むには旧東海道を渡る必要があるのだが、商店街が見えたので
踏切を渡らずにそちらを進む。

商店街は南武支線のガード下方向にそれなりに伸びているようだが、詳細は判らない。
少なくとも、京浜急行沿いには飲み屋しかなかった。
しばらく行った先で踏切を渡り、旧東海道を進む。
この辺は人車分離がされていないので、歩きづらいが車もほとんどこないようだ。

途中鶴見市場駅から伸びる商店街のそばを通るが、一番栄えているであろう駅から
離れた位置を通っているため、詳細はわからない。わからないことだらけだ。
ひでのふはずっと横浜と川崎の市境は鶴見川だとばかり思っていたのだが
鶴見川の下流はそうではないことに始めて気がついた。

しかし鶴見川を渡るとぐっと横浜市っぽくなる。
横浜市だからかどうかはわからないが、
旧東海道の説明板がちらほら目に付くようになる。

さらに進んでカーブの先にある京急鶴見駅からまた電車に乗る。

【2008/02/03】 旅・鉄道 | トラックバック(0) | コメント(0) | page top↑
会社から家まで歩いて帰ってみる その7 京急鶴見→京急新子安
京急鶴見の駅を降りて旧東海道をまた歩く。
この辺は鶴見銀座と呼ばれているあたりのようだ。
夜8時前ぐらいに歩いたのだが、商店街ではBGMが流れていた。

旧東海道らしく、小泉米店や戸山生命堂の看板が目を引く。
しばらく進むと第一京浜にぶつかるので、国道駅まで歩く。
国道駅の構内は昭和どころか戦前の佇まいが残っているのであるが
残念ながら廃墟になっている場所が多い。もちろん営業中の店もあるが。

国道駅を旧東海道側に抜けると、そこは魚河岸だった。
魚屋ばかりが軒を連ねるが、鮮魚の看板どころか半数の店は看板を掲げていない。
夜遅かったのでほとんどの店が閉まっていたので、ここもまた昼間にきてみたい
ところの一つとなった。

さらに進むと生麦事件の現場を通る。
現場前は葬祭場になっていたのだが、なんか関連があるのだろうか?
産業道路と交わる辺りはラーメン屋が多いが、そこを抜けると
キリンビールの工場の横を通る。
工場が終わると、今度は生麦事件の碑の横をとおり、第一京浜と合流する。

第一京浜は進んでもつまらんので、滝坂から浅野高校の前を通ることに。
浅野高校前は少し高台になっているので、景色がよい。
そして新子安駅前の複雑な歩道橋を通って、
京急新子安から電車にのる。

【2008/02/06】 旅・鉄道 | トラックバック(0) | コメント(2) | page top↑
xerces-c++ に取り組んでみた その1
ひでのふは主にWindows上で動くプログラムを作る仕事をしているわけですが
たまーに unix とか linux で動かすプログラムを作る必要もあったりするわけです。

で、Windows上で動くプログラムの設定関連はレジストリを使っているわけですが
linux にはそんなものはありません。
そうなると、Windows用に作ったプログラムをlinuxに移植する際に、
レジストリ周りの処理を、設定を書いたファイルへのアクセス処理に変更する必要が
でてきます。

次に設定ファイルをどのようなフォーマットで書くか。
ini?csv?バカ言っちゃいけない。もうこれは XML 以外の選択肢はありません

XML をプログラムから扱うとなると、まずはXML翻訳機能を司る「パーサ」を選びます。
いろいろ試行錯誤した結果から言ってしまうと、
パーサ勉強するなら自分でパーサ作った方が早い
んですが、再発明は往々にして無駄な努力以外の何者でもないので
既に世の中に出回っているパーサを選択します。

linux への移植性の向上が目的の一つなので、MSXML は除外します。
残りは expat と xerces と XML4C ぐらいしかないわけですが
xerces が一番がメジャーと言う大変非科学的な理由で xerces にします。
てゆーか、Apache のやってる xerces と IBM のやってる XML4C は大変距離が近いため
ひでのふは xerces のプログラミングを XML4C のドキュメントを参考にすると言う
初歩的かつ根源的なミスに気が付かないまま、
うごかねーうごかねーと言っていたのは内緒です。

ちなみに XML4C は java と C++ 間の移植が簡単に出来ることを念頭において
設計されていますが、xerces は「java っぽくならない」ことを念頭に
設計されています。
java のアーキテクチュアがお気に召さないひでのふは、xerces を選択するのも
むべなるかなと言ったところでしょうか。

次に XML へのアクセス方式で、DOM と SAX のどちらを選択するかですが
レジストリの置き換えが目的なので、迷わず DOM です。
ちなみにDOMとSAXの違いは...
・DOM は XML を一気に読んで翻訳(parse)する。
・SAX は XML を1行読むたびに派生クラスのメソッドを呼び出す。
どちらも一長一短ありますが、DOM の方がレジストリの考え方に近いと思います。

最後に、参考書籍っつーかwebページですが、java で XML ですと結構 web ページも
充実しているんですが、xerces C++ に関しては日本語で書かれているものは
全く見当たりませんでした。
仕方がないので、java の記述を脳内でC++に変換したり、
Distribution にくっついてくる英語のリファレンスを翻訳してみたりと、
大変苦労しました。

すでに誰かが書いていることを、わざわざ書かないをモットーとしておりますが
どうも世の中には見当たらないようなので、こうして公開することにしました。

使用している xerces はここから Binary Distribution をダウンロードしました。
バージョンは Xerces-C++ 2.8.0 です。
開発環境は Visual Studio 2005 を使用していますが
環境依存にならないようなソースを書くよう心がけています。
続きを読む
【2008/02/07】 Xerces-C++ | トラックバック(0) | コメント(3) | page top↑
会社から家まで歩いて帰ってみる その8 京急新子安→仲木戸
京急新子安の駅を降りて山側に向かう。
駅前にオルト横浜と言う建物があるのだが、これが公団の団地とは驚いた。
潮見よりよかったんじゃないかと思える。特に窓から電車が見えるところとか。
ただし建物の中にある商店街は、FC店ばかりで全く面白味がない。

そのあと一之宮神社の近辺をうろつくが、この辺は区画整理が進んでいないので
少々迷った。結局神社の参道を抜けて入江橋に出る。

ここからは浜通りを進む。
この辺は江戸前の漁師や釣り船屋、屋形船をやっているところが多いようだが
夜なので不気味なほど静まり返っている場所であり、
第一京浜の一本裏手の道になるだけで、まるで別のところに来たような錯覚を受ける。

昔は船を置いていたであろうコンクリの建造物の中には、車ばかり止まっていて
まるでフジツボかケヤリムシの風情だ。

こんな情緒的な文章ばかりになっているのは、
あまり見るところはなかったと言うことだ。
この日は仲木戸から電車にのる。

そういえば昔、この辺でバイトしていたことがあったのだが、
その時仲木戸駅のガード下にいたホームレスの夫婦はもういなくなっていて
橋脚を囲むようにフェンスができていましたとさ。

【2008/02/08】 旅・鉄道 | トラックバック(0) | コメント(0) | page top↑
会社から家まで歩いて帰ってみる その9 仲木戸→横浜
仲木戸の駅を降りて浜通りの続きを目指す。
昔あったはずの第一京浜の角のラーメン屋は、中華料理屋になっていた。同じか?

浜通りはさらに細くなっていたが、やはり第一京浜のすぐ裏とは思えないくらいの
異空間ぶりを発揮していた。
しばらく進むと住宅街に出る。横浜駅まで歩けば20分強の場所なのだが、やはり駅から
遠いせいであろうか?住宅の集積化が進んでいる場所ではなかった。

そして棉花橋を渡ると、奥の高島線に丁度貨物列車が通過しているところだった。
高島線の踏切の手前を曲がると、急に新しい場所に出る。横浜ポートサイドだ。
ここもやはり三菱村の一部のようだ。
ただ、このくらい端っこにくると三菱の威光も隅々までは届かないようで
廃墟と新しい建物が、くっきり分かれて対比されている風景が面白い。

ポートサイドは1F部分が店舗になっている。、インディーズ系の店が多いようでは
あるがどこも年収一千万を越えるような人たち向けの店構えが正直鼻に付く。
ちなみにここから横浜駅までは徒歩20分と言ったところだろうが、ほとんど駅まで
濡れずにいかれるのは凄いんじゃないかなとは思った。

この日は横浜駅から電車に乗る。

【2008/02/13】 旅・鉄道 | トラックバック(0) | コメント(0) | page top↑
xerces-c++ に取り組んでみた その2
まず、XML の解説っつーとこんな分厚い本を買わされる嵌めになるわけですが
ただタグで括っただけの代物の扱いになんでこんな情報量が必要なの?
と思うのは当然かと思われます。ひでのふもそう思っていました。

XML 技術においては、XML 文書をデータ、XSL ファイルをスクリプトと
することでデータ変換プログラムの一丁あがりと言う使い方があります。
となると、プログラミング言語的な使い方もあるという事になり、
必然的にその情報量も多くならざるを得ないと言うのは想像できるかと思います。
また、XML から派生した技術も多く(SOAPとかな)それについても解説を加えるならば
これでもまだまだ足りないと言うことになります。

しかし、xerces の DOM で XML を扱うだけなら、それほど必要な知識はありません。

XML 文書とはタグで括られたテキストであると言う理解以外に必要な知識を
下記にまとめておきます。

・整形式のXML文書
→ XML の書式に従って書かれたテキストファイルを指します。
例え XML っぽい文書であっても(終了タグが欠けているとか)
整形式のXML文書で無い場合は、xerces は一切解析をしてくれません。
テキストエディタで XML 文書を作ると、知らず知らずのうちに整形式のXML文書で
なくなっていることがあるので、注意が必要です。

XML 1.0 の書式は JIS 規格で定義されています。
こっちの方がちょっとだけ読みやすいけれど、少し古いので注意。

・Document
→ XML 文書ファイルを指します。

・Element
→ タグで区切られたデータのかたまりを指します。例えば

<element attr="image.html">
 <node>イメージデータ</node>
</element>

と言った感じです。

・Node
→ 各要素を指します。例えば

<node>ノードデータ</node>

上記の例は タグを表す Node(Element の Node)と、
テキストデータを表す Node(Text の Node )の二つに分けられることになります。

ひでのふ的には Node と Element をごっちゃにしないことは、
XML への理解を進める上で、大変重要
だと考えます。

・Attribute
→ タグの中に書かれた属性を示します。例えば

<tags attr="image.html">イメージデータ</tags>

斜字の部分が Attribute です。
【2008/02/14】 Xerces-C++ | トラックバック(0) | コメント(12) | page top↑
xerces-c++ に取り組んでみた その3
ではまず DOM が使えることを確認しましょう。
以下のコードがビルドできることを確認してください。

-------- ここから --------

#include <stdio.h>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/SAXException.hpp>

#ifdef XERCES_CPP_NAMESPACE_USE
XERCES_CPP_NAMESPACE_USE
#endif

void main(int argc, char* argv[]) ;

void main(int argc, char* argv[])
{
  DOMDocument *p_document ; // C++
  XercesDOMParser *p_dom_parser ;

  try
  {
// initialize the XML library
    XMLPlatformUtils::Initialize() ;
    p_dom_parser = new XercesDOMParser() ;
    p_dom_parser -> parse( "xerces-test.xml" ) ;
    p_document = p_dom_parser -> getDocument() ;
    if( p_document != NULL )
    {
      printf( "XML File Opened\r\n" ) ;
    }
    else
    {
      printf( "XML File Open Failure\r\n" ) ;
    }
// terminate the XML library
    delete p_dom_parser ;
    XMLPlatformUtils::Terminate() ;
  }
  catch( DOMException dom_e )
  {
    printf( "Encount DOMException / code = %d / message = %s\r\n",
      dom_e.code,
      XMLString::transcode( dom_e.getMessage()) ) ;
  }
  catch( SAXException sax_e )
  {
    printf( "Encount SAXException / message = %s\r\n",
      XMLString::transcode( sax_e.getMessage()) ) ;
  }
  catch(...)
  {
    printf( "Encount Exception\r\n" ) ;
  }
}

-------- ここまで --------

・コンパイルが通らないときは、ヘッダが見えてないか、コピペしたソースの
全角スペースを削除し切れてないかのどちらかです。
・リンカが通らないときは、XMLのライブラリが見えてないからです。

とりあえず、動く動かないは別にして、ビルドが通れば準備はOKです。

出来た実行ファイルから見えるところに、以下の内容で xerces-test.xml を作成すると

-------- ここから --------
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
データセットっす。
</dataset>
-------- ここまで --------

コンソールに XML File Opened と表示されるはずです。

【ソースコードの解説】

・XMLPlatformUtils::Initialize() ;
・XMLPlatformUtils::Terminate() ;
この二つのメソッドを、それぞれプログラムの先頭と終わりで呼び出す必要があります。

・XercesDOMParser クラス
xerces に DOM で XML を解析させるのはとても簡単で、単に XercesDOMParser クラスの
インスタンスを起こし、parse メソッドの引数に XML ファイル名を与えるだけです。

うんまあ解析結果を取り出す方法に辿り着くのが激しくめんどくさかったわけですが。

・メソッド失敗時の戻り値は NULL
parse メソッドに引き渡したファイルが存在しないぐらいでは例外は吐きません。
上記のソースのように、戻り値のポインタを判断して処理を進める必要があります。
これは DOM と頭に付くクラスのメソッドに、すべて共通した性質です。

・try ~ catch
それでも一応リファレンスには例外吐くよって書いてあるので、
try ~ catch は必須です。
捕まえるべき例外は DOMException と SAXException です。
XMLException ってのもあるんですが、これは XMLException から派生した例外を
自分で作って吐かない限り、捕まえる必要はありません。

・文字列
xerces の文字列はすべて XMLCh 型です。中身は UTF-16 文字列です。
char ポインタはそのままでは扱えません。
printf みたいに文字列を char ポインタで引き渡す必要がある場合は、

XMLString::transcode( e.getMessage()) ) ;

のようにする必要があります。

【2008/02/15】 Xerces-C++ | トラックバック(0) | コメント(0) | page top↑
台湾新幹線来たる
えび姉の同級生のママンからこれ買ってきてもらいますた。

DSC01508.jpg


ちょいとレアなアイテムが手に入って嬉しいです。
いや嬉しいのはもちろんえびちゅですよ。
続きを読む
【2008/02/16】 旅・鉄道 | トラックバック(0) | コメント(2) | page top↑
xerces-c++ に取り組んでみた その4
次に XML 文書の中身が取得できるようにします。
以下のコードがビルドできることを確認してください。
使用する XML 文書は前回と同じです。

-------- ここから --------

#include <stdio.h>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/SAXException.hpp>

#ifdef XERCES_CPP_NAMESPACE_USE
XERCES_CPP_NAMESPACE_USE
#endif

void main(int argc, char* argv[]) ;
void view_xml( DOMDocument *pDoc ) ;

void main(int argc, char* argv[])
{
  XercesDOMParser *p_dom_parser ;
  DOMDocument *p_document ;

  try
  {
// initialize the XML library
    XMLPlatformUtils::Initialize();
    p_dom_parser = new XercesDOMParser();
    p_dom_parser -> parse( "xerces-test.xml" ) ;
    p_document = p_dom_parser -> getDocument() ;
    if( p_document != NULL )
    {
      printf( "XML File Opened\r\n" ) ;
      view_xml( p_document ) ;
    }
    else
    {
      printf( "XML File Open Failure\r\n" ) ;
    }
// terminate the XML library
    delete p_dom_parser ;
    XMLPlatformUtils::Terminate() ;
  }
  catch( DOMException dom_e )
  {
    printf( "Encount DOMException / code = %d / message = %s\r\n",
      dom_e.code,
      XMLString::transcode( dom_e.getMessage()) ) ;
  }
  catch( SAXException sax_e )
  {
    printf( "Encount SAXException / message = %s\r\n",
      XMLString::transcode( sax_e.getMessage()) ) ;
  }
  catch(...)
  {
    printf( "Encount Exception\r\n" ) ;
  }
}

void view_xml( DOMDocument *pDoc )
{
  DOMElement *p_element ;
  DOMNode *p_node ;

  p_element = pDoc -> getDocumentElement() ;
  if( p_element != NULL )
  {
    printf( "Element : %s\r\n",
      XMLString::transcode( p_element -> getNodeName())) ;
    printf( "Element Value : %s\r\n",
      XMLString::transcode( p_element -> getNodeValue())) ;
    p_node = p_element -> getFirstChild() ;
    if( p_node != NULL )
    {
      printf( "Node Type : %d\r\n", p_node -> getNodeType()) ;
      printf( "Node Name : %s\r\n",
        XMLString::transcode( p_node -> getNodeName())) ;
      printf( "Node Value : %s\r\n",
        XMLString::transcode( p_node -> getNodeValue())) ;
    }
  }
}

-------- ここまで --------

実行ファイルを実行すると、コンソールに以下の内容が表示されるはずです。

XML File Opened
Element : dataset
Element Value : (null)
Node Type : 3
Node Name : #text
Node Value :
データセットっす。

今度はノードの中身を表示することができました。

【ソースコードの解説】

・view_xml 関数
前回との main 関数との違いは、この view_xml 関数を呼び出しているかいないか
だけです。
xerces で DOM を使用する場合、初めと終わりは常に同じ処理を行うので、
次回からは main 関数は省略し、view_xml 関数の内容だけを書くことにします。

・DOMDocument::getDocumentElement メソッド
Document からルートの Element を得るためのメソッドです。
ルートの Element は XML 文書一つに付きかならず一つと決まってるっぽいです。

・DOMElement::getNodeName メソッドと DOMElement::getNodeValue メソッド
Element の Node の名前を取得します。
これに違和感を感じるようでしたら、とりあえずそーゆーものと割り切ってください。
ちなみに、Element の名前は取れても DOMElement::getNodeValue メソッドは
必ず NULL を返します。

・DOMENode::getNodeName メソッドと DOMNode::getNodeValue メソッド
このソースでは、Text の Node の名前を取ろうとしているので、xerces が勝手に
振った名前が取られます。もちろん値は取得できます。
ちゃんと改行も込みで取得できているところもポイントです。

・DOMENode::getNodeType メソッド
戻り値は Node の種別を意味する short が返されます。
判定の必要があるなら、以下の enum 値が使えます。

DOMENode::ELEMENT_NODE = 1
DOMENode::ATTRIBUTE_NODE = 2
DOMENode::TEXT_NODE = 3
DOMENode::CDATA_SECTION_NODE = 4
DOMENode::ENTITY_REFERENCE_NODE = 5
DOMENode::ENTITY_NODE = 6
DOMENode::PROCESSING_INSTRUCTION_NODE = 7
DOMENode::COMMENT_NODE = 8
DOMENode::DOCUMENT_NODE = 9
DOMENode::DOCUMENT_TYPE_NODE = 10
DOMENode::DOCUMENT_FRAGMENT_NODE = 11
DOMENode::NOTATION_NODE = 12

getNodeType でぐぐると戻り値の日本語の説明が引っかかります。
java でも同じようですので、参考にすることができるでしょう。
また、TEXT_NODE だけを XML 文書から抽出したい!とかって思うのなら
DOMNodeFilter クラスの使用を検討してみると幸せになれるかもしれません。

何れにせよ、まだこの程度の XML 文書の読み込み程度では、レジストリの代わりに
するのは遠いです。
【2008/02/19】 Xerces-C++ | トラックバック(0) | コメント(0) | page top↑
xerces-c++ に取り組んでみた その5
次にお手近の Visual Studio .net のプロジェクトファイル(拡張子が .vcproj)を
開いてみてください。中身は XML です。

まさに、そのプロジェクトに関する設定が XML で保存されているわけですが
どのような書式で設定が保存されているかと言うと、タグとタグの間には
設定は一つもかかれておらず、以下のようにタグの中に設定が書かれています。

<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="xerces-test"
ProjectGUID="{3035AD25-066D-4A25-BE6E-8D6E258D8E7B}"
RootNamespace="xercestest"
Keyword="Win32Proj"
>
    :
    :
</VisualStudioProject>

この、タグの中の設定を Attribute と呼びます。
レジストリの置き換えを目指すなら、Microshaft 的に Attribute に設定を置くのが
よかろうとも思えるので、Attribute を表示するソースを以下に示します。


-------- ここから --------

void view_xml( DOMDocument *pDoc )
{
  DOMElement *p_element ;
  DOMNode *p_node, *p_attr_node ;
  XMLCh attr[100];
  DOMNamedNodeMap *p_map ;

  p_element = pDoc -> getDocumentElement() ;
  if( p_element != NULL )
  {
    printf( "Element : %s\r\n",
      XMLString::transcode( p_element -> getNodeName())) ;
    printf( "Element Value : %s\r\n",
      XMLString::transcode( p_element -> getNodeValue())) ;
      XMLString::transcode( "href", attr, 99);
    printf( "Element Attribute : %s\r\n",
      XMLString::transcode( p_element -> getAttribute( attr ))) ;
    p_node = p_element -> getFirstChild() ;
    if( p_node != NULL )
    {
      printf( "Node Type : %d\r\n", p_node -> getNodeType()) ;
      printf( "Node Name : %s\r\n",
        XMLString::transcode( p_node -> getNodeName())) ;
      printf( "Node Value : %s\r\n",
        XMLString::transcode( p_node -> getNodeValue())) ;
    }
  }
}

-------- ここまで --------

次に、使用する XML ファイルの内容を以下に示します。

-------- ここから --------
<?xml version="1.0" encoding="UTF-8"?>
<dataset href="http://hidenov.co.ru/index.html">
データセットっす。
</dataset>
-------- ここまで --------

実行ファイルを実行すると、コンソールに以下の内容が表示されるはずです。

XML File Opened
Element : dataset
Element Value : (null)
Element Attribute : http://hidenov.co.ru/index.html
Node Type : 3
Node Name : #text
Node Value :
データセットっす。

Attribute "href" の値を表示することができました。

でも、ルートの Element にすべての設定値を書き込むのは、いくらなんでも乱暴です。


【2008/02/20】 Xerces-C++ | トラックバック(0) | コメント(0) | page top↑
xerces-c++ に取り組んでみた その6
さらにお手近の Visual Studio .net のプロジェクトファイル(拡張子が .vcproj)を
開いて、もう一度よくみてください。

当然ながらルートの Element だけではなく、子 Element が入れ子になって
記述されています。

<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="xerces-test"
ProjectGUID="{3035AD25-066D-4A25-BE6E-8D6E258D8E7B}"
RootNamespace="xercestest"
Keyword="Win32Proj"
>
    :
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
    :
</VisualStudioProject>

レジストリも木構造のデータ構造を持つので、置き換えを目指すなら子 Element の
Attribute から設定を読み込む必要があります。
子 Element の Attribute を表示するソースを以下に示します。

-------- ここから --------

void view_xml( DOMDocument *pDoc )
{
  DOMElement *p_element ;
  DOMNode *p_node, *p_attr_node ;
  XMLCh attr[100];
  DOMNodeList *p_node_list ;
  XMLSize_t node_size, i ;
  DOMNamedNodeMap *p_map ;

  p_element = pDoc -> getDocumentElement() ;
  if( p_element != NULL )
  {
    printf( "Element : %s\r\n", XMLString::transcode( p_element -> getNodeName())) ;
    p_node_list = p_element -> getChildNodes() ;
    if( p_node_list != NULL )
    {
      node_size = p_node_list -> getLength() ;
      printf( "Node Size = %d\r\n", node_size ) ;
      for( i=0; i<node_size; i++ )
      {
        p_node = p_node_list -> item(i) ;
        printf( "Node Type : %d\r\n", p_node -> getNodeType()) ;
        printf( "Node Name : %s\r\n", XMLString::transcode( p_node -> getNodeName())) ;
        p_map = p_node -> getAttributes() ;
        if( p_map != NULL )
        {
          XMLString::transcode( "name", attr, 99) ;
          p_attr_node = p_map -> getNamedItem( attr ) ;
          if( p_attr_node != NULL )
          {
            printf( "Attributes : %s\r\n", XMLString::transcode( p_attr_node -> getNodeValue())) ;
          }
        }
      }
    }
  }
}

-------- ここまで --------

次に、使用する XML ファイルの内容を以下に示します。

-------- ここから --------
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<node name="Person1"></node>
</dataset>
-------- ここまで --------

実行ファイルを実行すると、コンソールに以下の内容が表示されるはずです。

XML File Opened
Element : dataset
Node Size = 3
Node Type : 3
Node Name : #text
Node Type : 1
Node Name : node
Attributes : Person1
Node Type : 3
Node Name : #text

子 Element の Attribute "name" の値を表示することができました。

では Node Type が 1 以外の Node はなんなんでしょうか?
最初の Node Type = 3 の Node は、タグ dataset のものです。
最後の Node Type = 3 の Node は、タグ node のものです。
xerces は、なにも無くともタグに囲まれた部分を Text の Node として
認識するようです。

【ソースコードの解説】

・DOMElement::getChildNodes メソッド
子 Node のリストを取得するメソッドですが、例のように Element の Node もリストに
含めています。

・DOMNodeList::getLength メソッド と DOMNodeList::item メソッド
このメソッドで、DOMElement::getChildNodes で取得した Node がいくつあるかを
調べます。そして item メソッドで Node のインスタンスを取得します。
これは xerces の基本的な処理パターンです。

・DOMNode::getAttributes メソッド
Node の Attribute を取得するメソッドです。
DOMElement クラスには直接 Attribute 名から Attribute 値を取得するメソッド
getAttribute があるのですが、DOMNode クラスにはありません。
なので、一旦 DOMNamedNodeMap クラスに落としてやる必要があります。
ちなみに、Node に Attribute が無い場合は NULL が返されます。

・DOMNamedNodeMap::getNamedItem メソッド
Attribute 値を実際に取り出してるメソッドです。
結局 Attribute 値を取り出すまでに...
Document 取りぃ~の...
Element 取りぃ~の...
Node List 取りぃ~の...
Node 取りぃ~の...
Named Node Map 取りぃ~の...
Attribute 取りぃ~の...ってめんどくさいんじゃああと怒っていては始まりません。

【2008/02/21】 Xerces-C++ | トラックバック(0) | コメント(2) | page top↑
xerces-c++ に取り組んでみた その7
前回と同じソースで、次の XML 文書を読み込んでみます。

-------- ここから --------
<?xml version="1.0" encoding="UTF-8"?>
<family>
  <grand_father name="Ojiisan">
    <father name="Chichiue">
      <node name="jibun">
        <child name="Musuko">
          <grand_child name="Mago"/>
        </child>
      </node>
    </father>
  </grand_father>
</family>
-------- ここまで --------

コンソールには以下の内容が表示されます。

XML File Opened
Element : family
Node Size = 3
Node Type : 3
Node Name : #text
Node Type : 1
Node Name : grand_father
Attributes : Ojiisan
Node Type : 3
Node Name : #text

Node 名 grand_father の Attribute は取得できていますが、
さらにそこから先の子孫の Node については、Attribute が取得できていません。
まずは子 Node の Attribute を表示するソースを以下に示します。

-------- ここから --------

void view_xml( DOMDocument *pDoc )
{
  DOMElement *p_element ;
  DOMNode *p_node, *p_attr_node, *p_child_node ;
  XMLCh attr[100];
  DOMNodeList *p_node_list, *p_child_list ;
  XMLSize_t node_size, child_size, i, j ;
  DOMNamedNodeMap *p_map, *p_child_map ;

  p_element = pDoc -> getDocumentElement() ;
  if( p_element != NULL )
  {
    printf( "Element : %s\r\n", XMLString::transcode( p_element -> getNodeName())) ;
    p_node_list = p_element -> getChildNodes() ;
    if( p_node_list != NULL )
    {
      node_size = p_node_list -> getLength() ;
      printf( "Node Size = %d\r\n", node_size ) ;
      for( i=0; i<node_size; i++ )
      {
        p_node = p_node_list -> item(i) ;
        printf( "Node Type : %d\r\n", p_node -> getNodeType()) ;
        printf( "Node Name : %s\r\n", XMLString::transcode( p_node -> getNodeName())) ;
        p_map = p_node -> getAttributes() ;
        if( p_map != NULL )
        {
          XMLString::transcode( "name", attr, 99) ;
          p_attr_node = p_map -> getNamedItem( attr ) ;
          if( p_attr_node != NULL )
          {
            printf( "Attributes : %s\r\n", XMLString::transcode( p_attr_node -> getNodeValue())) ;
          }
        }
// 子 Node の Attribute 表示 ------->
        p_child_list = p_node -> getChildNodes() ;
        if( p_child_list != NULL )
        {
          child_size = p_child_list -> getLength() ;
          printf( "Node Size = %d\r\n", child_size ) ;
          for( j=0; j<child_size; j++ )
          {
            p_child_node = p_child_list -> item(j) ;
            printf( "Node Type : %d\r\n", p_child_node -> getNodeType()) ;
            printf( "Node Name : %s\r\n", XMLString::transcode( p_child_node -> getNodeName())) ;
            p_child_map = p_child_node -> getAttributes() ;
            if( p_child_map != NULL )
            {
              XMLString::transcode( "name", attr, 99) ;
              p_attr_node = p_child_map -> getNamedItem( attr ) ;
              if( p_attr_node != NULL )
              {
                printf( "Attributes : %s\r\n", XMLString::transcode( p_attr_node -> getNodeValue())) ;
              }
            }
          }
        }
// <-------- 子 Node の Attribute 表示
      }
    }
  }
}

-------- ここまで --------

実行ファイルを実行すると、今度はコンソールに以下の内容が表示されるはずです。

XML File Opened
Element : family
Node Size = 3
Node Type : 3
Node Name : #text
Node Size = 0
Node Type : 1
Node Name : grand_father
Attributes : Ojiisan
Node Size = 3
Node Type : 3
Node Name : #text
Node Type : 1
Node Name : father
Attributes : Chichiue
Node Type : 3
Node Name : #text
Node Type : 3
Node Name : #text
Node Size = 0

子 Node の Attribute "name" の値を表示することができました。

さらなる子孫 Node の Attribute 値を表示したいのであれば、ソース中の
子 Node の Attribute 表示
で囲われた部分を何段も入れ子にしていけばいいわけですが、
これではキリがありません。

【ソースコードの解説】

・DOMNode::getChildNodes メソッド
DOMNode クラスにも子 Node のリストを取得するメソッドがあります。
【2008/02/22】 Xerces-C++ | トラックバック(0) | コメント(0) | page top↑
我が家の家計 2008/2
今月の増加分:107878
今までの増加:215368
車の減価償却引当て:270000

ガス代電気代が先月よりあがってますorz。

それでもあまりでかい出費がなかったので家計はプラスです。
光熱費が1万円余計にかかったところで
所詮外食1回半分と言ってしまえばそれまでですからね。
カードの支払いもいつもの支払い以外はほとんどありませんでした。

てゆーか、今月のプラスででかいのは児童手当です。

ようやく家計の浮きが20万円超えたのでトイレ交換の手配を始めました。
【2008/02/23】 家計 | トラックバック(0) | コメント(2) | page top↑
xerces-c++ に取り組んでみた その8
もっとエレガントに処理する方法は無いかと言うと...そう

再帰

を使えばよいのです。

すべての子孫 Node の Attribute を表示するソースを以下に示します。

-------- ここから --------

void view_xml( DOMDocument *pDoc )
{
  DOMElement *p_element ;
  DOMNodeList *p_node_list ;

  p_element = pDoc -> getDocumentElement() ;
  if( p_element != NULL )
  {
    printf( "Element : %s\r\n", XMLString::transcode( p_element -> getNodeName())) ;
    p_node_list = p_element -> getChildNodes() ;
    view_node_list( p_node_list ) ;
  }
}

void view_node_list( DOMNodeList *pNodeList )
{
  DOMNode *p_node, *p_attr_node ;
  DOMNodeList *p_node_list ;
  XMLSize_t node_size, i, attr_size, j ;
  DOMNamedNodeMap *p_map ;

  if( pNodeList != NULL )
  {
    node_size = pNodeList -> getLength() ;
    printf( "Node Size = %d\r\n", node_size ) ;
    for( i=0; i<node_size; i++ )
    {
      p_node = pNodeList -> item(i) ;
      if( p_node -> getNodeType() == DOMNode::ELEMENT_NODE )
      {
        printf( "Node Name : %s\r\n", XMLString::transcode( p_node -> getNodeName())) ;
        p_map = p_node -> getAttributes() ;
        if( p_map != NULL )
        {
          attr_size = p_map -> getLength() ;
          for( j=0; j<attr_size; j++ )
          {
            p_attr_node = p_map -> item(j) ;
            if( p_attr_node != NULL )
            {
              printf( "Attribute %s : %s\r\n",
                XMLString::transcode( p_attr_node -> getNodeName()),
                XMLString::transcode( p_attr_node -> getNodeValue())) ;
            }
          }
        }
        p_node_list = p_node -> getChildNodes() ;
        view_node_list( p_node_list ) ;
      }
    }
  }
}

-------- ここまで --------

実行ファイルを実行すると、今度はコンソールに以下の内容が表示されるはずです。

XML File Opened
Element : family
Node Size = 3
Node Name : grand_father
Attribute name : Ojiisan
Node Size = 3
Node Name : father
Attribute name : Chichiue
Node Size = 3
Node Name : node
Attribute name : jibun
Node Size = 3
Node Name : child
Attribute name : Musuko
Node Size = 3
Node Name : grand_child
Attribute name : Mago
Node Size = 0

すべての子孫 Node の Attribute "name" の値を表示することができました。

ホントに基本的な事項を扱うだけで再帰を使わなければならない xerces の敷居の
高さには恐れ入りますが、何れにせよ、木構造のデータを扱うのであれば
再帰を使うのは必然と言えます。

前回と比べ、機能が向上しているにも関わらずソースが短くて済んでいるのが
なによりの証左でしょう。

今回の例では Node の取得に getChildNodes メソッドと item メソッドを使って
いますが、代わりに getFirstChild メソッドと getNextSibling メソッドを使う
やりかたもあります。好みに応じて好きなほうを選んでください。

ここまでやれば、レジストリの代わりとして XML が使えると思います。
つってもまだこれだけだと読み込みだけですが。

【ソースコードの解説】

・view_node_list 関数
再帰処理のキモです。
新しく追加した関数なので、プロトタイプ宣言を忘れずに追加してください。
view_node_list 関数の中から、再度 view_node_list 関数を呼び出しています。
このような記述をすることにより、木構造がいくら深くても辿り着くことができます。

何気に Attribute の取得に DOMNamedNodeMap::getNamedItem を使わず、代わりに
getLength と item の組み合わせを使っています。
今回の処理方式ですと、事前に Attribute 名が判っていなくても、すべての Attribute
をリストアップできます。

もちろん、事前に取得する Attribute 名が判っているなら、
DOMNamedNodeMap::getNamedItem を使ったほうが速いと思います。

【2008/02/24】 Xerces-C++ | トラックバック(0) | コメント(0) | page top↑
xerces-c++ に取り組んでみた その9
読み込みが出来たので次は書き込みに取り組んでみます。

「ほとんどカラ」の Document を出力するソースを以下に示します。

-------- ここから --------

#include <stdio.h>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/SAXException.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>

#ifdef XERCES_CPP_NAMESPACE_USE
XERCES_CPP_NAMESPACE_USE
#endif

void main(int argc, char* argv[]) ;
void create_xml( DOMDocument *pDoc ) ;
//void view_xml( DOMDocument *pDoc ) ;
//void view_node_list( DOMNodeList *pNodeList ) ;

void main(int argc, char* argv[])
{
  DOMImplementation *p_impl ;
  DOMDocument *p_document ;
  DOMWriter *p_writer ;
  LocalFileFormatTarget *p_file ;

  try
  {
    XMLPlatformUtils::Initialize();
    p_impl = DOMImplementation::getImplementation() ;
    if( p_impl != NULL )
    {
      p_document = p_impl -> createDocument() ;
      if( p_document != NULL )
      {
        p_writer = p_impl -> createDOMWriter() ;
        if( p_writer != NULL )
        {
          p_writer -> setFeature( XMLString::transcode( "format-pretty-print" ), true ) ;
          p_file = new LocalFileFormatTarget( "write-test.xml" ) ;
          if( p_file != NULL )
          {
            create_xml( p_document ) ;
            if( p_writer -> writeNode( p_file, *p_document ) != false )
            {
              printf( "XML Document Write Complete\r\n" ) ;
            }
            else
            {
              printf( "XML Document Write Failure\r\n" ) ;
            }
            p_file -> flush() ;
            delete p_file ;
          }
          else
          {
            printf( "LocalFileFormatTarget Create Failure\r\n" ) ;
          }
          delete p_writer ;
        }
        else
        {
          printf( "DOMWriter Create Failure\r\n" ) ;
        }
        delete p_document ;
      }
      else
      {
        printf( "DOMDocument Create Failure\r\n" ) ;
      }
    }
    else
    {
      printf( "DOMImplementation Create Failure\r\n" ) ;
    }
// terminate the XML library
    XMLPlatformUtils::Terminate() ;
  }
  catch( DOMException dom_e )
  {
    printf( "Encount DOMException / code = %d / message = %s\r\n",
      dom_e.code,
      XMLString::transcode( dom_e.getMessage()) ) ;
  }
  catch( SAXException sax_e )
  {
    printf( "Encount SAXException / message = %s\r\n",
      XMLString::transcode( sax_e.getMessage()) ) ;
  }
  catch(...)
  {
    printf( "Encount Exception\r\n" ) ;
  }
}

void create_xml( DOMDocument *pDoc )
{
}

-------- ここまで --------

実行ファイルを実行すると、write_test.xml に以下の内容が出力されるはずです。

-------- ここから --------
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
-------- ここまで --------

はい。Element は一つもありません。まさにカラの Document です。
これだけのモノを吐くだけでも...

Implementation 拵え~の...
Document 拵え~の...
Writer 拵え~の...
FormatTarget 拵え~のと、ってめんどくさいんじゃああと怒っていては始まりません。

どっかで見たような展開ですね。先が思いやられます。

【ソースコードの解説】

・DOMImplementation::createDocument メソッドと
DOMImplementation::createDOMWriter メソッド
実は DOMDocument も DOMWriter も new でインスタンスを作ることができません。
てゆーか、xerces では直接 new でインスタンスが生成できないクラスが多いです。
new を使うとコンストラクタ内で発生したエラーが例外でないと通知できないってのが
嫌がられているのでしょうか?よくわかりません。

ちなみに、この連載のその3のコードを参考にして
DOMImplementation::createDocument の部分を XercesDOMParser::parse と
XercesDOMParser::getDocument に置き換えると、読み込んだ XML ファイルに対して
追記が行えるようになります。

・DOMWriter::setFeature メソッド
プロパティ format-pretty-print に対して true を設定していますが
これを怠ると出力する XML 文書に改行も字下げも入りません。orz
DOM Level 3 からの実装なのですが、これ以前はわざわざ Xalan 使わなきゃ
いけなかったんだろうか...

・create_xml 関数
今回この関数の実装はカラです。
やっぱり main はこれからも一緒のソースになりそうなので、
次々回から main は省略し create_xml 関数のみを記述します。
ってこれもどっかで見たような展開だ。

・LocalFileFormatTarget::flush メソッドとデストラクタ
開いたファイルを閉じるときの作法です。
flush メソッドはもしかすると単なるスタブかもしれません。
LocalFileFormatTarget のインスタンスを開放した時点で、出力先ファイルの
ハンドルが開放されるようです。

これを忘れると、プロセスが終了するまで別のプロセスで出力した XML ファイルを
開くことができません。

・DOMDocument と DOMWriter のデストラクタ
xerces では getなんちゃらメソッド で取得したインスタンスは
明示的に開放する必要がない
のですが、createなんちゃらメソッド で生成したインスタンスは、明示的に
開放しないと、フツーにお漏らしします。
もちろん new で生成したインスタンスは開放する必要があります。
ちなみに DOMImplementation のインスタンスを開放すると
XMLPlatformUtils::Terminate で落ちます。

【2008/02/27】 Xerces-C++ | トラックバック(0) | コメント(0) | page top↑
バッファオーバーフロー対策を考えてみる
現在複数のサイトに入る予定のプロダクトを C++ で作ろうと考えています。
複数のサイトで動くので、バッファオーバーフロー対策もしっかりやらねばならんと思い
いろいろ検討をしてみました。

具体的には strcpy, sprintf 等の
バッファオーバーフローの可能性がある関数の追放です。

ちなみに、strlen とか文字列内にNULL文字がないと吹っ飛ぶ系は、
単なるバグなので脅威とは考えません。

対策案その1:
strcpy を strncpy に置き換える。
sprintf を snprintf に置き換える。

一見これで解決かなと思われるわけですが
strncpy の 第3パラメータはコピー先の大きさを示しているわけではない
のと
snprintf はそもそも Windows では実装がない
ので、対策になりません。orz
同様の理由で li/unux 系では実装がない strcpy_s なんかも使えません。
あまり科学的な理由ではありませんが、LibSafe は時期尚早でしょう。

対策案その2:
STLを使う。

じゃあこれでいいじゃんとも思うわけですが...
確かにバッファオーバーフローの可能性はなくなりますが
サービス拒否攻撃はもっと簡単になります。orz

対策案その3:
いっそのこと自分で strcpy, sprintf を実装する。

コピー先の大きさを計算してから領域を確保し、
そこに文字列を生成すればいいだけです。

じゃあ作ればいいじゃんとも思うわけですが...
確かにバッファオーバーフローの可能性はなくなります。
サービス拒否攻撃を防ぐことも可能です。
しかし今度はメモリリークに頭を悩ませることになります。orz

ひでのふはメモリリークも単なるバグと考えるので、
そうなるとこれで対策することになるわけですが、
この手のライブラリを自分で管理してオーソライズしてリスクまで負うのは
いくらなんでもコスト高すぎで、見合いません。

続きを読む
【2008/02/28】 技術 | トラックバック(0) | コメント(2) | page top↑
今月の屑株 2008/2
今月は以下の銘柄を売却

YOZAN を 131円 で 1株 --- 4719円の損失

今月は以下の銘柄を購入

ダイナシティを2810円で2株

まず YOZAN ですがこれは100株→1株の株式併合で、
単位にするには98株も買い増さなければならないので損切りです。
1株売って残りの1株は株券を取得しましたので
今後 YOZAN には資本維持費用で購ってもらうことになります。

YOZAN 買った2006年10月にはこんなこと書いていたわけですが
いまや当時は望みの綱であった
ブロードバンド用のアクセスポイントサービスも止めています。
まさに本業は株券発行業と言うしかない状態です。



> アドテックスのようなことにならないとは思いますが...

と当時は書いていたわけですが、
今後は間違いなくサンライズテクノロジーのようなことになるかと思います。
どっちにしろ株主にとってはイヤな結末でしかありませんが...

で、今月買ったダイナシティの方ですが...

続きを読む
【2008/02/29】 屑株 | トラックバック(0) | コメント(0) | page top↑
| ホーム |