欢迎访问 外汇EA下载与MT4/MT5自动交易资源 - 聚合外汇EA、黄金EA、量化交易工具与自动化交易实战内容。
登录 注册

EasyXML - XML 解析器 - MetaTrader 5 库

author emer | 916 人阅读 | 0 人评论 |

主要目的和能力

EasyXML 是一个简单但功能强大的 XML 解析器,它可以从三个不同的源读取和解析 XML:

它完全用本机 MQL5 编写,仅依赖 Windows 本机“wininet.dll”从 URL 获取 XML 文档。

只要您尝试解析的文档格式正确,EasyXML 就会以(几乎)无限的节点深度读取 XML 和 XHTML。确实如此不是但是,根据 DTD 或 XSLT 样式表验证 XML。

MQL5 集成

EasyXML 的节点类继承自 MQL5 原生对象节点存储在CArray对象

遍历 DOM 树节点时,可以使用公共 EasyXML 方法以及 MQL5 本机函数轻松操作 DOM 树节点,以从 DOM 检索数据并将数据存储到 DOM。

URL 文件缓存和调试

由于人们不能总是依赖 RSS Feed 的正常运行时间,一旦第一次从 URL 成功加载 Feed,EasyXML 就可以存储 Feed 的 XML 缓存文件。如果 Feed 由于某种原因而关闭,则用户可以使用缓存文件而不是实时 Feed 进行解析。

由于 XML 和 XHTML 文档往往会出错,因此 EasyXML 有一个调试选项。虽然它无法修复损坏的 XML,但它肯定有助于检测错误所在。如果打开,它将打印解析的节点的详细信息。

除此之外,无论调试打开还是关闭,发生的任何错误都将始终被跟踪和打印。

只需在脚本中包含基类即可,然后就可以开始使用了:

//+------------------------------------------------------------------+
//|包括                                                         |
//+------------------------------------------------------------------+
#包括

首先,在脚本中创建 EasyXML 类的实例。然后设置调试和/或文件缓存并调用可用方法之一来加载 XML 并开始解析:

//+------------------------------------------------------------------+
//|脚本程序启动函数                                   |
//+------------------------------------------------------------------+
空白 启动时()
  {
  // 创建 CEasyXml 类的实例   CEasyXml EasyXmlDocument;

  // 可选的调试   EasyXmlDocument.setDebugging(真的);

  // 设置Url缓存文件   EasyXmlDocument.setUrlCacheFile(“forexcalendar.xml”);

  // 方法 1:从 URL 加载 XML  如果(EasyXmlDocument.loadXmlFromUrl(“http://www.forexfactory.com/ffcal_week_this.xml”))
     {
      readRecursive(EasyXmlDocument.getDocumentRoot());
     }

  // 清除 DOM   EasyXmlDocument.Clear();

  // 方法 2:从字符串加载 XML  如果(EasyXmlDocument.loadXmlFromString(内容siblingcontent))
     {
      readRecursive(EasyXmlDocument.getDocumentRoot());
     }

  // 清除 DOM   EasyXmlDocument.Clear();

  // 方法 3:从文件加载 XML  如果(EasyXmlDocument.loadXmlFromFile(“forexcalendar.xml”))
     {
      readRecursive(EasyXmlDocument.getDocumentRoot());
     }
  }

出于演示目的,显示了所有三种方法。通常,您不会立即需要所有这些,尽管可以清除中间的 DOM 树并重新开始解析,甚至可以从另一个源开始解析。只需使用 Clear() 命令来擦除已解析的 DOM 树。 setDebugging() 和 setUrlCacheFile() 是可选的,如果不需要,则不必调用。

EasyXmlDocument.getDocumentRoot() 将始终返回 DOM 树的根节点。包括根节点在内的所有节点均为 CEasyXmlNode 类型,它本身源自 MQL5 CObject(如前所述)。从这里开始,EasyXml 以及 CArrayObj 和 CObject 的所有方法都可以并排使用来遍历解析的 DOM 树。

以下示例显示了 readRecursive() 的实现,该函数是在最后一个代码示例中调用的全局函数:

//+------------------------------------------------------------------+
//|递归读取 xml                                               |
//+------------------------------------------------------------------+
整数readRecursive(CEasyXmlNode *ActualNode,整数iNode级别=0)
  {
  // 输出变量  细绳s空间;
  细绳输出;

  // 缩进输出以获得更好的可读性  字符串初始化(sSpace,iNodeLevel*4,字符串获取字符” “,0));

  // 连接输出字符串   s输出 += s空间 +整数转字符串(iNodeLevel) +“ - 节点名称:'”+ ActualNode.getName() +“'”;
   sOutput += (ActualNode.getValue()) ?“ 价值: '”+ ActualNode.getValue() +“'”:””;

  // 遍历属性节点  为了整数我=0; i“ || 属性”+整数转字符串(我+1)+“:”+属性.getName()+“' 价值: '”+属性.getValue()+“'”;
     }

  打印(s输出);

  // 遍历子节点  为了整数j=0; j1);
     }

  返回0);
  }

XML 文档的递归读取比内联读取具有很大的优势,尽管它可能并不适合所有需求。在节点上调用 Attributes() 将获取所有已解析的属性,而 Children() 将获取存储在实际节点中的子节点。两种方法都返回包含元素的 CArrayObj。对这些对象调用 Total() 可以在 for() 循环中使用来迭代元素。 getName() 和 getValue() 将返回存储在节点中的实际内容。

当然,也可以内联迭代节点:

//+------------------------------------------------------------------+
//|脚本程序启动函数                                   |
//+------------------------------------------------------------------+
空白 启动时()
  {// 创建 CEasyXml 类的对象   CEasyXml EasyXmlDocument;// 设置调试   EasyXmlDocument.setDebugging(错误的);// 示例:内联遍历 dom 树  如果(EasyXmlDocument.loadXmlFromUrl(“http://www.forexfactory.com/ffcal_week_this.xml”))
     {
      CEasyXmlNode *RootNode=EasyXmlDocument.getDocumentRoot();

      //遍历根节点      为了整数我=0; i打印(整数转字符串(一)+” “+ChildNode.getName());

        //遍历子节点        为了整数j=0; j打印(整数转字符串(一)+“-”+整数转字符串(j)+“   ”+子节点.getName()+” | “+SubNode.getValue());
           }
        }
     }
  }

迭代的工作原理与递归示例相同,只是必须为要读取的每个节点级别建立单独的 for() 循环。

除此之外,如果需要的话,还可以逐步遍历 DOM 并操作单个元素:

//+------------------------------------------------------------------+
//|脚本程序启动函数                                   |
//+------------------------------------------------------------------+
空白 启动时()
  {// 创建 CEasyXml 类的对象   CEasyXml EasyXmlDocument;// 设置调试   EasyXmlDocument.setDebugging(真的);// 示例 2:逐步遍历 DOM 树  如果(EasyXmlDocument.loadXmlFromString(内容siblingcontent))
     {
      CEasyXmlNode *Node=EasyXmlDocument.getDocumentRoot();
      打印(Node.getName());

      CEasyXmlNode *ChildNode=Node.FirstChild();
      打印(ChildNode.getName());

      // 如果手动向侧面移动,请始终检查有效指针。      尽管检查指针(ChildNode.Next())!=POINTER_INVALID)
        {
         ChildNode=ChildNode.Next();
        打印(ChildNode.getName());
        }

      CEasyXmlNode *ParentNode=ChildNode.Parent();
      打印(ParentNode.getName());

      // 回到根源:ParentNode 和 Node 是同一个对象的两个不同的描述符      打印“对象描述符的比较:ParentNode == Node ?”,ParentNode==Node);
     }
  }

这里所有可用的 EasyXML 方法以及 CObject 和 CArrayObj 的本机 MQL5 Iteration/Getter/Setter 都会发挥作用。

但请记住,其中一些函数不关心有效的内存访问,如果不成功,则仅返回 NULL。

在最后一个示例中,在同级节点上调用 ChildNode.Next()(不检查指针有效性)将导致严重的错误指针错误(= 错误的内存访问),这肯定会使脚本崩溃。因此,如果您需要手动单步执行或操作 DOM 树,请注意指针的有效性,只要它涉及 CObject 和 CArrayObj 类方法。

最重要的节点吸气剂

最重要的节点设置者

属性获取器/设置器

属性对象实现相同的 get/setName()、get/SetValue() 方法来存储和检索数据,就像节点对象一样。

这段代码正在积极开发中,并且与所有软件一样,并不声称没有错误或其他缺陷。使用 EasyXml 的风险由您自行承担,并在将该库实施到任何实时交易 EA 之前进行彻底测试。如果您遇到任何问题或使用方面有疑问,请随时与我联系。

用于获取 URL 内容的 wininet.dll 的集成使用WININET_测试经过整数。尽管这个库是建立在它自己独特的解析系统之上的,XML解析器写于玉纱是处理 MQL5 字符串操作的绝佳学习资源。



附件下载

📎 easyxml.mqh (23.9 KB)

📎 easyxmlattribute.mqh (3.03 KB)

📎 easyxmlerrordescription.mqh (3.31 KB)

📎 easyxmlnode.mqh (7.68 KB)

📎 examples_integration.mq5 (3.15 KB)

📎 example_inline_parsing.mq5 (1.9 KB)

📎 example_step_walking.mq5 (2.02 KB)

Source: MQL5 #1998

🔐
请登录后参与评论
注册满12小时后评论,即可解锁附件下载
立即登录