EasyXML - XML Parser - MetaTrader 5 Library | Trading Script Download - MT4/MT5 Resources
Main purpose and capabilities
EasyXML is a simple yet powerful XML parser that can read and parse XML from three different sources:
It is completely written in native MQL5 and relies only on Windows native "wininet.dll" to get XML documents from URLs.
EasyXML will read XML and XHTML with (almost) unlimited node depth, as long as the document you are trying to parse is well-formed. This is not true, however, when validating XML against a DTD or XSLT stylesheet.
MQL5 integration
EasyXML's node class inherits from MQL5 native object nodes are stored in CArray objects .
When traversing DOM tree nodes, you can easily manipulate DOM tree nodes using public EasyXML methods as well as MQL5 native functions to retrieve data from and store data in the DOM.
URL file caching and debugging
Since one cannot always rely on RSS feed uptime, EasyXML can store the feed's XML cache file once the feed is successfully loaded from the URL for the first time. If the feed is down for some reason, users can use cached files for parsing instead of the live feed.
Because XML and XHTML documents tend to have errors, EasyXML has a debugging option. While it won't fix corrupted XML, it will certainly help detect where the error lies. If turned on, it will print details of the parsed nodes.
In addition to this, any errors that occur will always be tracked and printed regardless of whether debugging is on or off.
Just include the base class in your script and you're ready to go:
//+------------------------------------------------------------------+ //|Include | //+------------------------------------------------------------------+ #include
First, create an instance of the EasyXML class in your script. Then set up debugging and/or file caching and call one of the available methods to load the XML and start parsing:
//+------------------------------------------------------------------+ //|Script program startup function | //+------------------------------------------------------------------+ blank start () { // Create an instance of the CEasyXml class CEasyXml EasyXmlDocument; // Optional debugging EasyXmlDocument.setDebugging( true ); //Set Url cache file EasyXmlDocument.setUrlCacheFile( "forexcalendar.xml" ); // Method 1: Load XML from URL if (EasyXmlDocument.loadXmlFromUrl( "http://www.forexfactory.com/ffcal_week_this.xml" )) { readRecursive(EasyXmlDocument.getDocumentRoot()); } // Clear the DOM EasyXmlDocument.Clear(); // Method 2: Load XML from string if (EasyXmlDocument.loadXmlFromString( "” )) { readRecursive(EasyXmlDocument.getDocumentRoot()); } // Clear the DOM EasyXmlDocument.Clear(); // Method 3: Load XML from file if (EasyXmlDocument.loadXmlFromFile( "forexcalendar.xml" )) { readRecursive(EasyXmlDocument.getDocumentRoot()); } } content Sibling content
For demonstration purposes, all three methods are shown. Typically you won't need all of this at once, although you can clear the intermediate DOM tree and start parsing again, even from another source. Simply use the Clear() command to erase the parsed DOM tree. setDebugging() and setUrlCacheFile() are optional and do not have to be called if not required.
EasyXmlDocument.getDocumentRoot() will always return the root node of the DOM tree. All nodes, including the root node, are of type CEasyXmlNode, which itself is derived from MQL5 CObject (as mentioned earlier). From here on, EasyXml and all methods of CArrayObj and CObject can be used side by side to traverse the parsed DOM tree.
The following example shows the implementation of readRecursive(), the global function called in the last code example:
//+------------------------------------------------------------------+ //|Recursively read xml | //+------------------------------------------------------------------+ integer readRecursive(CEasyXmlNode *ActualNode, integer iNode level = 0 ) { // Output variable string s space; string output; //Indent output for better readability String initialization (sSpace,iNodeLevel* 4 , string get characters ( " " , 0 )); //Connect the output string s output += s space + integer to string (iNodeLevel) + "-Node name: '" + ActualNode.getName() + "'" ; sOutput += (ActualNode.getValue()) ? "Value: '" + ActualNode.getValue() + "'" : "" ; // Traverse the attribute nodes in order ( integer i = 0 ; i" || Attribute" + Integer to string (i + 1 ) + ":" + Attribute.getName()+ "' Value: '" + Attribute.getValue()+ "'" ; } print (soutput); // Traverse the child nodes for ( integer j= 0 ; j 1); } return ( 0 ); }
Recursive reading of XML documents has significant advantages over inline reading, although it may not be suitable for all needs. Calling Attributes() on a node will get all resolved attributes, while Children() will get the children stored in the actual node. Both methods return a CArrayObj containing the elements. Calling Total() on these objects can be used in a for() loop to iterate over elements. getName() and getValue() will return the actual content stored in the node.
Of course, nodes can also be iterated inline:
//+------------------------------------------------------------------+ //|Script program startup function | //+------------------------------------------------------------------+ blank start () { // Create an object of CEasyXml class CEasyXml EasyXmlDocument; // Set debugging EasyXmlDocument.setDebugging( wrong ); // Example: Inline traversal of dom tree if (EasyXmlDocument.loadXmlFromUrl( "http://www.forexfactory.com/ffcal_week_this.xml" )) { CEasyXmlNode *RootNode=EasyXmlDocument.getDocumentRoot(); //Traverse the root node in order ( integer i = 0 ; iPrint ( integer to string (1) + ” “ +ChildNode.getName()); //Traverse the child nodes for ( integer j= 0 ; j Print ( integer to string (1) + “-” + integer to string (j) + “ ” + subnode.getName()+ ” | “ +SubNode.getValue()); } } } }
Iteration works the same as the recursive example, except that a separate for() loop must be built for each node level to be read.
In addition to this, you can step through the DOM and manipulate individual elements if desired:
//+------------------------------------------------------------------+ //|Script program startup function | //+------------------------------------------------------------------+ blank start () { // Create an object of CEasyXml class CEasyXml EasyXmlDocument; // Set debugging EasyXmlDocument.setDebugging( true ); // Example 2: Traverse the DOM tree step by step if (EasyXmlDocument.loadXmlFromString( "” )) { CEasyXmlNode *Node=EasyXmlDocument.getDocumentRoot(); print (Node.getName()); CEasyXmlNode *ChildNode=Node.FirstChild(); print (ChildNode.getName()); // If manually moving sideways, always check for a valid pointer. Although ( check pointer (ChildNode.Next())!= POINTER_INVALID ) { ChildNode=ChildNode.Next(); print (ChildNode.getName()); } CEasyXmlNode *ParentNode=ChildNode.Parent(); print (ParentNode.getName()); // Back to the root: ParentNode and Node are two different descriptors of the same object. Print ( "Comparison of object descriptors: ParentNode == Node?" , ParentNode==Node); } } content Sibling content
All available EasyXML methods as well as native MQL5 Iteration/Getter/Setter of CObject and CArrayObj will come into play here.
But keep in mind that some of these functions don't care about valid memory access and just return NULL if unsuccessful.
In the last example, calling ChildNode.Next() on a sibling node (without checking pointer validity) will result in a severe bad pointer error (= bad memory access), which will definitely crash the script. Therefore, if you need to manually step or manipulate the DOM tree, be aware of pointer validity as long as it involves CObject and CArrayObj class methods.
The most important node getter
The most important node setter
Property getters/setters
Property objects implement the same get/setName(), get/SetValue() methods to store and retrieve data as node objects.
This code is under active development and, like all software, no claim is made to be free of bugs or other defects. Use EasyXml at your own risk and test the library thoroughly before implementing it into any live trading EA. If you encounter any problems or have questions about usage, please feel free to contact me.
The integration of wininet.dll for getting URL content is tested using WININET_INTEGER . Although this library is built on its own unique parsing system, the XML parser written by Yusha is an excellent learning resource for handling MQL5 string operations.
Attachment download
📎 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
💡 Featured Recommendations
✍️ Latest by the author
- •
- •
- •
- •
- •
- •
📌 Popular topics
- •
- •
- •
- •
- •
- •
- •
- •
🔗 You May Be Interested In
- •
- •
- •
- •
- •
- •