Participe de nossa página de fãs
Coloque um link para ele, e permita que outras pessoas também o avaliem
Avalie seu funcionamento no terminal MetaTrader 5
EasyXML - Analisador XML - biblioteca para MetaTrader 5
- Visualizações:
- 2096
- Avaliação:
- Publicado:
- 2014.01.14 12:28
- Atualizado:
- 2016.11.22 07:34
- Precisa de um robô ou indicador baseado nesse código? Solicite-o no Freelance Ir para Freelance
Propósito e habilidades Principais
EasyXML é um simples mas poderoso analisador XML que pode ler e analisar XML a partir de três fontes diferentes:
- URL
- Arquivo de entrada
- String de entrada
Ele foi escrito completamente em MQL5 nativo e baseia-se na "wininet.dll" nativa do Windows somente para buscar documentos XML a partir de uma URL.
EasyXML vai ler XML, bem como XHTML com (quase) profundidade de nó infinita, desde que o documento que você esteja tentando analisar é bem formatado. Ele não valida o XML contra um DTD ou folhas de estilo XSLT.
Integração MQL5
As classes Nó de EasyXML são herdadas de CObject nativo em MQL5 e os nós são armazenados em uma CArrayObj.
Ao caminhar nos nós da árvore DOM, ela pode ser manipulada facilmente usando os métodos públicos de EasyXML, bem como as funções nativas em MQL5 para recuperar os dados e armazenar dados para o DOM.
Cache e Depuração da URL do Arquivo
Como não se pode sempre contar com RSS Feed Uptimes, EasyXML pode armazenar um arquivo de cache XML da alimentação, uma vez que ela seja carregada a partir de uma URL com sucesso pela primeira vez. O usuário então pode usar o arquivo de cache em vez do Live Feed para análise, caso a alimentação seja desligado por algum motivo.
Se os documentos XML e XHTML tendem a ser erróneos, EasyXML tem uma opção de depuração. Enquanto ele não pode reparar um XML quebrado, ele certamente irá ajudar a detectar onde está o erro. Se estiver ativado ele irá imprimir informações detalhadas dos nós analisados.
Além disso, os erros que ocorrem sempre serão rastreados e impressos, mesmo se a depuração for ligada ou desligada.
Uso Básico
Basta incluir a classe base em seus scripts que ela estará configurada e pronto para ir:
//+------------------------------------------------------------------+ //| Includes | //+------------------------------------------------------------------+ #include <EasyXML\EasyXml.mqh>
Em primeiro lugar, no seu script, crie uma uma instância da classe EasyXML. Em seguida, defina a depuração e/ou arquivo em cache e chame um dos métodos disponíveis para carregar o XML e começar a análise:
//+------------------------------------------------------------------+ //| Função Start do Script | //+------------------------------------------------------------------+ void OnStart() { // Cria uma instância da classe CEasyXml CEasyXml EasyXmlDocument; // Depuração Opcional EasyXmlDocument.setDebugging(true); // Define a Url do Cache do arquivo EasyXmlDocument.setUrlCacheFile("forexcalendar.xml"); // Método 1: Carregar o XML da URL if(EasyXmlDocument.loadXmlFromUrl("http://www.forexfactory.com/ffcal_week_this.xml")) { readRecursive(EasyXmlDocument.getDocumentRoot()); } // Limpa o DOM EasyXmlDocument.Clear(); // Método 2: Carregar o XML da string if(EasyXmlDocument.loadXmlFromString("<root><child attr='value'>content</child><sibling>siblingcontent</sibling></root>")) { readRecursive(EasyXmlDocument.getDocumentRoot()); } // Limpa o DOM EasyXmlDocument.Clear(); // Método 3: Carregar o XML do arquivo if(EasyXmlDocument.loadXmlFromFile("forexcalendar.xml")) { readRecursive(EasyXmlDocument.getDocumentRoot()); } }
Para fins de demonstração de, são mostrados todos os três métodos. Normalmente você não vai precisar de todos eles de uma vez, embora seja possível para limpar a árvore DOM no meio e começar a analisar de novo, mesmo a partir de outra fonte. Basta usar o comando Clear() para apagar a árvore DOM analisada. setDebugging() e setUrlCacheFile() são opcionais e não têm de ser chamado, caso eles não forem necessários.
EasyXmlDocument.getDocumentRoot() sempre retornará o nó raiz da árvore DOM. Todos os nós, incluindo o nó da raiz são do tipo CEasyXmlNode, que por si só deriva do MQL5 CObject (como mencionado anteriormente). Todos os métodos de EasyXml, bem como de CArrayObj e CObject podem ser usados lado a lado, para orientar a árvore DOM analisada.
O exemplo a seguir mostra a implementação de readRecursive(), a função global que é chamada no último exemplo do código:
//+------------------------------------------------------------------+ //| Ler xml recursiva | //+------------------------------------------------------------------+ int readRecursive(CEasyXmlNode *ActualNode,int iNodeLevel=0) { // vars de saída string sSpace; string sOutput; // récuo de saída para uma melhor legibilidade StringInit(sSpace,iNodeLevel*4,StringGetCharacter(" ",0)); // Concatenar string de saída sOutput += sSpace + IntegerToString(iNodeLevel) + " - Node Name: '" + ActualNode.getName() + "'"; sOutput += (ActualNode.getValue()) ? " Value: '" + ActualNode.getValue() + "'" : ""; // Itera através de 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); // Percorrer os nós filhos for(int j=0; j<ActualNode.Children().Total(); j++) { CEasyXmlNode *ChildNode=ActualNode.Children().At(j); readRecursive(ChildNode,iNodeLevel+1); } return(0); }
Leitura recursiva de documentos XML tem grandes vantagens em relação a leitura inline, embora possa não ser apropriado para todas as necessidades. Chamando Attributes() em um nó, ele vai buscar todos os atributos analisados, enquanto que Children() irá obter os nós filhos armazenados no nó atual. Ambos os métodos retornam um CArrayObj contendo os elementos. Chamando Total() nesses objetos pode ser usado em um loop for() para iterar sobre os elementos. getName() e getValue() irá retornar o conteúdo real armazenado no nó.
Claro que é possível interagir sobre nós em linha, bem como:
//+------------------------------------------------------------------+ //| Função Start do Script | //+------------------------------------------------------------------+ void OnStart() { // Cria o objeto da classe CEasyXml CEasyXml EasyXmlDocument; // define depuração EasyXmlDocument.setDebugging(false); // Exemplo: Andando pela linha árvore DOM if(EasyXmlDocument.loadXmlFromUrl("http://www.forexfactory.com/ffcal_week_this.xml")) { CEasyXmlNode *RootNode=EasyXmlDocument.getDocumentRoot(); //Iterar por nó raiz for(int i=0; i<RootNode.Children().Total(); i++) { CEasyXmlNode *ChildNode=RootNode.Children().At(i); Print(IntegerToString(i)+" "+ChildNode.getName()); //Percorrer por nós filhos for(int j=0; j<ChildNode.Children().Total(); j++) { CEasyXmlNode *SubNode=ChildNode.Children().At(j); Print(IntegerToString(i)+"-"+IntegerToString(j)+" "+SubNode.getName()+" | "+SubNode.getValue()); } } } }
A iteração funciona exatamente como no exemplo recursivo, exceto que um loop for() separado deve ser estabelecido para cada nível de nó a ser lido.
Além disso, também é possível caminhar passo a passo por DOM e manipular elementos de únicos, se necessário:
//+------------------------------------------------------------------+ //| Função Start do Script | //+------------------------------------------------------------------+ void OnStart() { // Cria o objeto da classe CEasyXml CEasyXml EasyXmlDocument; // define depuração EasyXmlDocument.setDebugging(true); // Exemplo 2: Andando através da arvore DOM passo a passo 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()); // Sempre verifique se há indicações válidas se pisar sidewards manualmente. while(CheckPointer(ChildNode.Next())!=POINTER_INVALID) { ChildNode=ChildNode.Next(); Print(ChildNode.getName()); } CEasyXmlNode *ParentNode=ChildNode.Parent(); Print(ParentNode.getName()); // Voltar para a raiz: ParentNode e Nó são dois descritores diferentes de um mesmo objeto Print("Comparison of object descriptors: ParentNode == Node ? ",ParentNode==Node); } }
Aqui estão todos os métodos EasyXML disponíveis, bem como as nativas em MQL5 Iteration/Getter/Setter de CObject e CArrayObj entram em jogo.
Tenha em mente, porém, que algumas dessas funções não se importam se acessam uma memória válida retornando NULL, caso eles não sucederem.
No último exemplo chamando ChildNode.Next() no nó irmão - sem verificar a validade do ponteiro - implicaria em uma grave falha de ponteiro ruim (= mal acesso da memória), que irá definitivamente travar o script. Então, se você tiver a necessidade de intensificar ou manipular a árvore DOM manualmente, cuide de validar o ponteiro, enquanto se trata do CObject e métodos de classe CArrayObj.
Getters mais importantes
Método | Propósito | Retorno |
---|---|---|
Chilrden() | Obter todas as crianças do nó | CArrayObj - contendo CEasyXmlNodes |
Attributes() | Obter todos os atributos do nó | CArrayObj - contendo CEasyXmlAttributes |
Parent() | Obter nó pai | CEasyXmlNode (CObject) |
LastChild() | Obter último nó filho | CEasyXmlNode (CObject) |
FirstChild() | Receber o primeiro nó filho | CEasyXmlNode (CObject) |
getName() | Obter nome do nó | string |
getValue() | Obter valor do nó (conteúdo do texto) | string |
getAttribute(string pName) | Obter atributo pelo nome especificado | string |
Next() (Herdado de CObject) | Obter o próximo nó irmão | CEasyXmlNode (CObject) || NULL |
Prev() (Herdado de CObject) | Obter nó irmão anterior | CEasyXmlNode (CObject) || NULL |
Setters mais importantes
Método | Propósito | Retorno |
---|---|---|
createChild(CEasyXmlNode *pChildNode) | criar um novo nó filho | CEasyXmlNode (CObject) - o novo nó filho |
createSibling(CEasyXmlNode *pSiblingNode) | criar um novo nó irmão | CEasyXmlNode (CObject) - o novo nó irmão |
setName(string pName) | define o nome do nó | void |
setValue(string pValue) | define o valor do nó (conteúdo do texto) | void |
setAttribute(string pName,string pValue) | define novo atributo ao nó | void |
Atributos getters/setters
Atributo dos objetos implementam os mesmos métodos get/setName(), get/SetValue() para armazenar e recuperar dados assim como os objetos de nó.
Responsabilidade
Este pedaço de código está em desenvolvimento ativo, e, como acontece com todos os softwares, não tem a pretensão de ser livre de bugs ou outros defeitos. Use EasyXml a seu próprio risco e teste exaustivamente antes de implementar esta libraray em qualquer EA de negociação real. Se você encontrar algum problema ou tiver dúvidas sobre o uso, por favor, não hesite em contatar-me.
Créditos
A Integração do wininet.dll usado para buscar o conteúdo da URL usa WININET_TEST por Integer. Embora esta biblioteca é construída sobre o seu próprio sistema de análise único, o Analisador XML foi escrito por yu-sha foi uma grande fonte de aprendizagem para lidar com operações de string em MQL5.
Traduzido do inglês pela MetaQuotes Ltd.
Publicação original: https://www.mql5.com/en/code/1998
Este indicador é uma pequena modificação do Indicador Fractals clássico. Você pode escolher o número ou as barras esquerda/direita para ter uma nova parte superior ou inferior, bem como um deslocamento do parâmetro.
Awesome ModifiedEste indicador é uma modificação do clássico indicador Awesome. Ele calcula a taxa suavizada da mudança de duas médias exponenciais.
O código foi projetado para ser uma simples referência de como criar (arrastar) painéis móveis e preenchê-lo com informações.
StepChoppy_v2Um indicador de força de tendência com oito estados.