このブログ「吟遊詩人の戯言」 の記事検索...

IXMLDOMNodeの検索PGサンプル

関連記事








こちらに,書き起こしてみましたわん


必要とされる方,お持ち帰り,ドゾー
バグってたら,スマソ(笑




やっと,検索部が,安定した
残りは,ノードからをジャンスカ引っ張ってくる実装だけやなぁ

こいつの実装数,半端なく多い
今日中に半分終わるかなぁ...

 
 
 
 

【Delphi】IXMLDOMNodeのノード追跡用コードのサンプル

関連記事




必要に迫られて,書き起こしてみた

悔いは無い(爆

また,どっかでこの手の追っかけ部,実装作業があったときの
自分自身のサンプル用に

次はC#辺りで,やりそう


なお,どことなく,ORCA~Claimの香りがするのは気のせいではない(笑

//**********************************************
//指定ノードの検索(再帰利用)
//
//nd : 検索開始点のノード (IXMLDOMNode)
//ndName : 検索対象のノード名称
//
//return : 見つけたノードオブジェクト(見つからなかったらnull)
//**********************************************
function TClaimInput.SearchNode(nd: IXMLDOMNode; ndName: string): IXMLDOMNode;
var
    i : integer;
    st : string;
begin

    result := nil;
    for i  :=  0 to  nd.childNodes.Get_length - 1  do
    begin
        st := nd.childNodes.item[i].Get_nodeName();
        if  st = ndName then
         begin
            result := nd.childNodes.item[i];
         end
        else
         begin
            result := SearchNode(nd.childNodes.item[i], ndName);
         end;

        if result <> nil then
        begin
            break;
        end;
    end;
end;

//**********************************************
//指定ノードの検索(再帰利用)(Overload)
//
//nd : 検索開始点のノード (IXMLDOMNode)
//ndName : 検索対象のノード名称
//attrName : 検索対象のノード属性名称
//attrVal  : 検索対象のノード属性値
//
//return : 見つけたノードオブジェクト(見つからなかったらnull)
//**********************************************
function TClaimInput.SearchNode(nd: IXMLDOMNode; ndName: string; attrName : string; attrVal : string): IXMLDOMNode;
var
    i : integer;
    j : integer;
    stn : string;
    stv : string;

    fl : boolean;
begin

    result := nil;
    for i  :=  0 to  nd.childNodes.Get_length - 1  do
    begin
        fl := false;

        stn := nd.childNodes.item[i].Get_nodeName();
        if  stn = ndName then
         begin
            for j := 0 to nd.childNodes.item[i].attributes.Get_length - 1 do
            begin
                stn := nd.childNodes.item[i].attributes.item[j].Get_nodeName();
                stv := nd.childNodes.item[i].attributes.item[j].Get_text();
                if (stn = attrName) and (stv = attrVal) then
                begin
                    fl := true;
                    break;
                end;
            end;
         end;

        if fl = true then
         begin
            result := nd.childNodes.item[i];
         end
        else
         begin
            result := SearchNode(nd.childNodes.item[i], ndName, attrName, attrVal);
         end;

        if result <> nil then
        begin
            break;
        end;
    end;
end;

//**********************************************
//指定ノードの1層上のノードを返す
//
//nd : 検索開始点のノード (IXMLDOMNode)
//
//return : 一個上位のノードオブジェクト
//**********************************************
function TClaimInput.SearchNodeParent(nd: IXMLDOMNode): IXMLDOMNode;
begin
    result := nd.Get_parentNode;
end;

【Delphi】インデント付きでXMLの保存

関連記事








ここのページにサンプルがありまして

コードを抜粋しておきます

procedure SaveXMLToFile(FileName: TFileName);
var
    lStringList: TStringList;
    Writer: IMXWriter;
    Reader: IVBSAXXMLReader;
begin
    Writer := CoMXXMLWriter.Create;
    Reader := CoSAXXMLReader.Create;

    Writer.byteOrderMark := True;
    Writer.omitXMLDeclaration := False;
    Writer.indent := True;

    Reader.contentHandler := Writer as IVBSAXContentHandler;
    Reader.dtdHandler := Writer as IVBSAXDTDHandler;
    Reader.errorHandler := Writer as IVBSAXErrorHandler;
    Reader.putProperty('http://xml.org/sax/properties/lexical-handler',    Writer);
    Reader.putProperty('http://xml.org/sax/properties/declaration-handler',    Writer);

    Reader.parse(FDoc);

    lStringList := TStringlist.Create;
    lStringList.Text := Writer.output;
    lStringList.SaveToFile(FileName);
end;

んで,お手軽にインデント付きでXMLが出力できるんですが…

XMLファイルの先頭が必ず

<?xml version="1.0" encoding="UTF-16" standalone="no"?>



エンコード,UTF-8で出したいのに,UTF-16でしか,出力できない感じ orz

んで,まえ,学校プロジェクトで吐き出していたXML@VC++版は,エンコードが,綺麗にS-JISと出てたよなぁ~
と思い出し…

んで,つらつら調べたら
エンコードを変えるには,IStreamを使うしか,手がなさそうな感じ…

VC++版を気合入れて,Delphi版へ書き換えてみましたわぁ~

あ,外部のpasファイルがいりますんで,注意!

//uses ShLwApi;

//**********************************************
//インデントつきでXMLの保存
//
//**********************************************
procedure TClaimOutput.SaveIndentXML(fname: string; pDoc: IXMLDOMDocument);
var
    stmFile : IStream;
    wrt : IMXWriter;
    rdr : IVBSAXXMLReader;
begin

    SHCreateStreamOnFile(
            PChar(fname),
            STGM_READWRITE or STGM_SHARE_DENY_WRITE or STGM_CREATE,
            stmFile
        );

    wrt := CoMXXMLWriter.Create;
    wrt.indent := True;
    wrt.encoding := 'utf-8';
    wrt.version := '1.0';
    wrt.output := stmFile;

    rdr :=  CoSAXXMLReader.Create;
    rdr.contentHandler := wrt as IVBSAXContentHandler;

    rdr.parse(pDoc);
end;

SHCreateStreamOnFile()を利用するため,ShLwApi.pasがいります
Delphi5じゃ,なかったです
んで,ここから,ダウンロードしてきました


とりあえず,インデント付きでXMLは出力されていますわぁ~~♪

MSXML利用時,DTD関連のエラーでXMLが読めないときの対処

関連記事




いや,ずっぽりはまった(笑

MSXMLを利用して,ORCA-CLAIMの電文XMLを読み込もうとしたら
IXMLDOMDocument.Load()が,エラー吐いて,読めやしない

原因をあれこれ追っかけていったら,
MSXMLのパーサが,構文解析エラーを起こしている模様


CLAIM電文(MML)中

    <!DOCTYPE Mml SYSTEM….

の行を,コメントアウトすると
引きあがるようにはなる

でも,コメントアウトしたXMLをCLAIMに投げつけても
たぶん,エラー起こして,データ受信してくれないようなぁ

ってことで,さらに追っかけたら,こちらに,似たような事例…

IXMLDOMDocument.resolveExternals
IXMLDOMDocument.validateOnParse

二つのプロパティ,FALSEにすれば,読み込むまでは可能になるとのこと

今回は,読み込んで,一部書き換えて,保存するって,作業なんで
これ,FALSEにしても,実害ないかな?

DELPHIで書き起こしてみました


//メンバとして定義
    FdomDocument   : IXMLDOMDocument;

//**********************************************
//コンストラクタ
//
//**********************************************
constructor TClaimOutput.Create;
begin
  inherited;

    FdomDocument       :=  CoDOMDocument.Create();      //インスタンス生成
    FdomDocument.async :=  true;    //同期モードがいいらしい

end;

//**********************************************
//XMLテンプレートの読み込み
//
//**********************************************
function TClaimOutput.Load : Boolean;
var
    wb : WordBool;
    a : Integer;
    l : Integer;
    st : string;
    st1 : string;
begin
    if (FileExists(FInPath + XML_INFILENAME) = false) then       //ファイルが見つからない場合
    begin
        Result := false;
        exit;
    end;

    FdomDocument.resolveExternals := false;     //二つのプロパティをFALSE
    FdomDocument.validateOnParse  := false;
    wb := FdomDocument.load(FInPath + XML_INFILENAME);   //CLAIM-XML読み込み

    if  ( wb = true) then  begin     //OK時
        result := true;
    end else begin            //NG時
        a  := FdomDocument.parseError.errorCode;
        l  := FdomDocument.parseError.line;
        st := FdomDocument.parseError.reason;
        st1 := FdomDocument.parseError.srcText;

        FErrorStr := IntToHex(a, 8) + ',' + IntToStr(l) + ',' + st + ',' + st1;
        //ShowMessage(FErrorStr);
        result := false;
    end;

end;

とりあえず,本番の送受信テストまでは
この実装で行きますです

やばかったら,そのとき,また悩む,ということで(笑


あと,MSXMLのバージョン表はこちらですわん
とりあえず,MSXML3にて作業は続けております

IXMLDOMDocumentのインスタンス

関連記事








解放動作,いらないのかなぁ??

それらしきメソッドもないし
サンプル,解放動作,やってるコードないし?


どうも,気色悪いなぁ...


もうちょっと調べてみよう