私たちのファンページに参加してください
- ビュー:
- 1166
- 評価:
- パブリッシュ済み:
- 2016.10.19 09:36
- アップデート済み:
- 2016.11.22 07:34
-
このコードに基づいたロボットまたはインジケーターが必要なら、フリーランスでご注文ください フリーランスに移動
主な目的と能力
EasyXMLは3つの異なるソースからXMLを読み取って解析することができるシンプルで強力なXMLパーサーです。
- URL
- ファイル入力
- 文字列入力
これは完全にネイティブMQL5で書かれており、URLからXMLドキュメントを取得するためにWindowsネイティブのwininet.dllに依存するだけです。
解析しようとしている文書にフォーマットの間違えがなければ、EasyXMLは(ほぼ)無限のノードの深さでXMLだけでなくXHTMLも読むことができます。しかしながらDTDやXSLTスタイルシートに対してのXMLの検証は行われません。
MQL5統合
EasyXMLのNodeクラスはMQL5ネイティブのCObjectから継承され、ノードはCArrayObjに格納されます。
DOMツリーをトラバーサルする際、ノードは、パブリックのEasyXMLメソッドだけでなくDOMデータの取得/格納のためのMQL5ネイティブ関数を使用して簡単に操作することができます。
URLファイルキャッシュとデバッグ
常にRSSフィードの更新に依存することはできないため、EasyXMLは、最初のURLからの詠み入れが成功した後にフィードのXMLキャッシュファイルを保存することができます。フィードが何らかの理由でダウンした場合、ユーザーは構文解析のためにライブフィードの代わりにキャッシュファイルを使用することができます。
XMLとXHTMLドキュメントには間違いがありがちなので、EasyXMLにはデバッグオプションがあります。壊れたXMLの修復はできませんが、間違いがどこにあるかを検出するのには確かに役立ちます。オンにすると解析されたノードの詳細情報が出力されます。
それに加えて、デバッグのオン/オフにかかわらず、発生したエラーは常に追跡されて出力されます。
基本的な使用法
スクリプトに基本クラスをインクルードすれば設定は完了し準備が整います。
//+------------------------------------------------------------------+ //| インクルードする | //+------------------------------------------------------------------+ #include <EasyXML\EasyXml.mqh>
初めにスクリプトでEasyXMLクラスのインスタンスを作成します。その後、デバッグおよび/またはファイルキャッシュを設定して、XMLを読み込んで構文解析を開始するために利用可能なメソッドのいずれかを呼び出します。
//+------------------------------------------------------------------+ //| スクリプトプログラム開始関数 | //+------------------------------------------------------------------+ void OnStart() { // CEasyXmlクラスインスタンスを作成する CEasyXml EasyXmlDocument; // 任意のデバッグ EasyXmlDocument.setDebugging(true); // Urlキャッシュファイルを設定する EasyXmlDocument.setUrlCacheFile("forexcalendar.xml"); // 方法1:URLからXMLを読み込む if(EasyXmlDocument.loadXmlFromUrl("http://www.forexfactory.com/ffcal_week_this.xml")) { readRecursive(EasyXmlDocument.getDocumentRoot()); } // DOMをクリアする EasyXmlDocument.Clear(); // 方法2:文字列からXMLを読み込む if(EasyXmlDocument.loadXmlFromString("<root><child attr='value'>content</child><sibling>siblingcontent</sibling></root>")) { readRecursive(EasyXmlDocument.getDocumentRoot()); } // DOMをクリアする EasyXmlDocument.Clear(); // 方法3:ファイルからXMLを読み込む if(EasyXmlDocument.loadXmlFromFile("forexcalendar.xml")) { readRecursive(EasyXmlDocument.getDocumentRoot()); } }
3つの方法のすべてはデモのために示されています。間にDOMツリーをクリアして別のソースからでも再び解析を開始することも可能ですが、通常はそれらのすべてが一度に必要になることはありません。ただClear()コマンドを使って解析されたDOMツリーを消去します。setDebugging()とsetUrlCacheFile()は任意で、必要がなければ呼び出される必要がありません。
EasyXmlDocument.getDocumentRoot() は常にDOMツリーのルートノードを戻します。ルートノードを含むすべてのノードはCEasyXmlNode型で(前記されたように)MQL5 CObjectから派生しています。ここからは、CArrayObj、CObjectとEasyXmlのメソッドは、解析されたDOMツリーをトラバーサルするのにすべて並べて使用されることができます。
次の例は、最後のコード例で呼び出されるreadRecursive()グローバル関数の実装を示しています。
//+------------------------------------------------------------------+ //| 再帰的にXMLを読み取る | //+------------------------------------------------------------------+ int readRecursive(CEasyXmlNode *ActualNode,int iNodeLevel=0) { // 出力変数 string sSpace; string sOutput; // 読みやすくするために出力をインデントする StringInit(sSpace,iNodeLevel*4,StringGetCharacter(" ",0)); // 出力文字列を連結する sOutput += sSpace + IntegerToString(iNodeLevel) + " - Node Name: '" + ActualNode.getName() + "'"; sOutput += (ActualNode.getValue()) ?" Value: '" + ActualNode.getValue() + "'" : ""; // AttributeNodesを反復処理する for(int i=0; i<ActualNode.Attributes().Total(); i++) { CEasyXmlAttribute *Attribute=ActualNode.Attributes().At(i); sOutput+=" || Attribute "+IntegerToString(i+1)+": '"+Attribute.getName()+"' Value: '"+Attribute.getValue()+"'"; } Print(sOutput); // 子ノードを反復処理する for(int j=0; j<ActualNode.Children().Total(); j++) { CEasyXmlNode *ChildNode=ActualNode.Children().At(j); readRecursive(ChildNode,iNodeLevel+1); } return(0); }
XML文書の再帰的な読み込みはインラインでの読み込みを超える大きな利点を有していますがすべてのニーズに適していないかもしれません。ノードでのAttributes()の呼び出しはすべての解析された属性を取得し、Children() は実際のノードに格納されている子ノードを取得します。両メソッドは要素を含むCArrayObjを戻します。これらのオブジェクトでのTotal()の呼び出しは要素を反復処理するfor()ループで使用できます。getName()とgetValue()はノードに格納された実際の内容を戻します。
もちろん、インラインでノードを反復処理することも同様に可能です。
//+------------------------------------------------------------------+ //| スクリプトプログラム開始関数 | //+------------------------------------------------------------------+ void OnStart() { // CEasyXmlクラスオブジェクトを作成する CEasyXml EasyXmlDocument; // デバッグを設定する EasyXmlDocument.setDebugging(false); // 例:インラインでのDOMツリーのトラバーサル if(EasyXmlDocument.loadXmlFromUrl("http://www.forexfactory.com/ffcal_week_this.xml")) { CEasyXmlNode *RootNode=EasyXmlDocument.getDocumentRoot(); // ルートノードから反復処理する for(int i=0; i<RootNode.Children().Total(); i++) { CEasyXmlNode *ChildNode=RootNode.Children().At(i); Print(IntegerToString(i)+" "+ChildNode.getName()); // 子ノードを反復処理する for(int j=0; j<ChildNode.Children().Total(); j++) { CEasyXmlNode *SubNode=ChildNode.Children().At(j); Print(IntegerToString(i)+"-"+IntegerToString(j)+" "+SubNode.getName()+" | "+SubNode.getValue()); } } } }
すべての読み取られるノードレベルのために別々のfor()ループが確立されなければいけないことを除いて、この反復は再帰的な例同様に動作します。
それに加えて、DOMをステップごとにトラバーサルして、必要に応じて、単一の要素を操作することも可能です。
//+------------------------------------------------------------------+ //| スクリプトプログラム開始関数 | //+------------------------------------------------------------------+ void OnStart() { // CEasyXmlクラスオブジェクトを作成する CEasyXml EasyXmlDocument; // デバッグを設定する EasyXmlDocument.setDebugging(true); // 例2:ステップごとのDOMツリーのトラバーサル if(EasyXmlDocument.loadXmlFromString("<root><child attr='value'>content</child><sibling>siblingcontent</sibling></root>")) { CEasyXmlNode *Node=EasyXmlDocument.getDocumentRoot(); Print(Node.getName()); CEasyXmlNode *ChildNode=Node.FirstChild(); Print(ChildNode.getName()); // 手動で横向きにステッピングする場合には、必ずポインタの有効性をチェックする while(CheckPointer(ChildNode.Next())!=POINTER_INVALID) { ChildNode=ChildNode.Next(); Print(ChildNode.getName()); } CEasyXmlNode *ParentNode=ChildNode.Parent(); Print(ParentNode.getName()); // ルートに戻る: ParentNodeとNodeは同じオブジェクトの2つの異なる記述である Print("Comparison of object descriptors: ParentNode == Node ?",ParentNode==Node); } }
ここで、利用可能なEasyXMLメソッドだけでなく、ネイティブMQL5のCObjectおよびCArrayObjのイテレーション/ゲッター/セッターすべての出番となります。
しかし、これらの機能のいくつかはメモリアクセスの有効性を気にせず、成功しない場合にはNULLを戻すことを覚えておいてください。<分節
最後の例では、ポインタの妥当性のチェックなしでの兄弟ノード上でのChildNode.Next()の呼び出しは非常に悪いポインタ・フォールト(=不良メモリアクセス)を起こし、スクリプトは必然的クラッシュします。<よって、DOMツリーを手動でトラバーサルまたは操作する必要がある場合はCObject とCArrayObjクラスメソッドに関係する限り、ポインタの有効性が確認されるべきです。
最も重要なノードゲッター
メソッド | 目的 | 戻す |
---|---|---|
Chilrden() | ノードのすべての子を取得する | CArrayObj - 含まれるCEasyXmlNodes |
Attributes() | ノードのすべての属性を取得する | CArrayObj - 含まれるCEasyXmlAttributes |
Parent() | 親ノードを取得する | CEasyXmlNode (CObject) |
LastChild() | 子から最後のノードを取得する | CEasyXmlNode (CObject) |
FirstChild() | 子から最初のノードを取得する | CEasyXmlNode (CObject) |
getName() | ノード名を取得する | string |
getValue() | ノード値を取得する(テキストの内容) | string |
getAttribute(string pName) | 指定された名前で属性を取得する | string |
Next()(CObjectから継承) | 次の兄弟ノードを取得する | CEasyXmlNode (CObject) || NULL |
Prev()(CObjectから継承) | 1つ前の兄弟ノードを取得する | CEasyXmlNode (CObject) || NULL |
最も重要なノードセッター
メソッド | 目的 | 戻す |
---|---|---|
createChild(CEasyXmlNode *pChildNode) | 新しい子ノードを作成する | CEasyXmlNode (CObject) - 新しい子ノード |
createSibling(CEasyXmlNode *pSiblingNode) | 新しい兄弟ノードを作成する | CEasyXmlNode (CObject) - 新しい兄弟ノード |
setName(string pName) | ノード名を設定する | void |
setValue(string pValue) | ノード値を設定する(テキストの内容) | void |
setAttribute(string pName,string pValue) | 新しいノードの属性を設定する | void |
属性ゲッター/セッター
属性オブジェクトは、ノードオブジェクトのようにデータを格納/取得する同じget/setName()、get/SetValue() メソッドを実装します。
免責条項
このコードの一片は活発に開発されており、すべてのソフトウェアと同様バグやその他の欠陥がないことを主張しません。EasyXmlはご自分のリスクで使用し、ライブ取引EAでこのライブラリを実装する前に 徹底的に検証されるべきです。使用状況に関する質問がおありか問題が発生した場合は、お気軽にご連絡ください。
クレジット
URLのコンテンツを取得するために使用されるwininet.dllの統合はWININET_TESTをIntegerで使用します。このライブラリは独自に構築され、ユニークな構文解析システムを持ちますがyu-sha によって書かれたXMLパーサーはMQL5の文字列操作に対応するための偉大な学習元でした。
MetaQuotes Ltdによって英語から翻訳されました。
元のコード: https://www.mql5.com/en/code/1998

入力パラメータでの時間枠選択オプションを持つJMASlope指標

入力パラメータでの時間枠選択オプションを持つSlopeDirectionLine指標