XML message wrapper

Want to work with XML as easy as in following examples, do not depend on XML format and have ability to change format to JSON?
Read XML message:
static void testReadMessage(Args _args)
{
    VKMessage       doc,
                    message,
                    activity,
                    id;
    int             a;
    str             xml = @'<Message>
    <Activity>
        <Id>ConfigurableProducts</Id>
    </Activity>
    <Activity>
        <Id>ConfigurableProducts2</Id>
    </Activity>
    <TestNode>TestNodeValue</TestNode>
</Message>';

    // construct message from source
    doc     = VKMessage::construct(xml);

    // select Message node, return same VKMessage type
    message = doc.selectNode('Message');
    //message = doc.selectNode('Message/Activity'); // to access directly Activity node

    // select Activity nodes in same way like 1 node selection
    message.selectNode('Activity');

    // get count of selected nodes and go though them
    for (a = 0; a < message.getNodeCount(); a++)
    {
        // getNextNode starts from the first node
        activity = message.getNextNode();

        // select inbound Id node and get it's value
        info(activity.selectNode('Id').getValue());
    }

    // sequential node selection
    info(doc.selectNode('Message').selectNode('TestNode').getValue());

    // use second parameter to select none existing nodes, getValue will return empty result in that case and you do not need to have additional check whether or not node was selected
    info(doc.selectNode('DoesNotExist', true).getValue());

    // This one will give runtime error
    doc.selectNode('DoesNotExist').getValue();
}
Write XML message:
static void testWriteMessage(Args _args)
{
    VKMessage       doc,
                    message,
                    activity,
                    id;

    // construct new message of correct type
    doc     = VKMessage::construct();

    // create new Message node. It will automatically append it to doc
    message = doc.createNode('Message');

    // create new ActivityNode which will be appended to Message node
    activity= message.createNode('Activity');

    // Create new Id node with value SomeId1 and append it to Activity node
    activity.createNode('Id', 'SomeId1');

    // Create additional Activity node on same Message level
    activity= message.createNode('Activity');
    activity.createNode('Id', 'SomeId2');

    // get source of created document, XML
    info(doc.getDocumentContent());
}
Select node with namespace:
        VKMessageXml   doc,
                        sendClubProSettings,
                        clubProsList;
 
        doc = VKMessage::construct(@'<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns0:sendClubProSettings xmlns:ns1="http://www.domain.com/docs/leisureClubPro" xmlns:ns0="http://leisureClubPro.ws.domain.com/">
        </ns0:sendClubProSettings>
    </S:Body>
</S:Envelope>');
        doc.addNamespace('S', 'http://schemas.xmlsoap.org/soap/envelope/');
        doc.addNamespace('ns0', 'http://leisureClubPro.ws.domain.com/');

        sendClubProSettings = doc.selectNode('S:Envelope/S:Body/ns0:sendClubProSettings');
       if (sendClubProSettings)
        {
            sendClubProSettings.createNode('TWSToken', 'token');
            clubProsList = sendClubProSettings.createNode('ClubProsList');
            clubProsList.createNode('Status', 'ADD');
            clubProsList.createNode('Id', '123');
        }
        // get source of created document, XML
        info(doc.getDocumentContent());

Base abstract class to support several message formats:
/// <summary>
/// Abstract class to handle messages of different formats
/// </summary>
abstract class VKMessage
{
    /// <summary>
    /// Create message node
    /// </summary>
    /// <param name = "_name">Name</param>
    /// <param name = "_value">Value</param>
    /// <param name = "_append">Append</param>
    /// <returns>VKMessage</returns>
    abstract public VKMessage createNode(str _name, str _value = '', boolean _append = true)
    {
    }

    /// <summary>
    /// Get document
    /// </summary>
    /// <returns>VKMessage</returns>
    abstract public VKMessage getDocument()
    {
    }

    /// <summary>
    /// Get document content
    /// </summary>
    /// <returns>string</returns>
    abstract public str getDocumentContent()
    {
    }

    /// <summary>
    /// Get next node
    /// </summary>
    /// <returns>VKMessageXml</returns>
    abstract public VKMessage getNextNode()
    {
    }

    /// <summary>
    /// Get node count
    /// </summary>
    /// <returns>Int</returns>
    abstract int getNodeCount()
    {
    }

    /// <summary>
    /// Get value
    /// </summary>
    /// <returns>str</returns>
    abstract public str getValue()
    {
    }

    /// <summary>
    /// Init from string message
    /// </summary>
    /// <param name = "_message">String</param>
    abstract public void initFromMessage(str _message)
    {
    }

    /// <summary>
    /// Select a node
    /// </summary>
    /// <param name = "_name">Name</param>
    /// <param name = "_returnEmptyIfNone">Return empty if none</param>
    /// <returns>VKMessage</returns>
    abstract public VKMessage selectNode(str _name, boolean _returnEmptyIfNone = false)
    {
    }

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name = "_message">Message</param>
    /// <param name = "_messageFormat">Message format</param>
    /// <returns>VKMessage</returns>
    static public VKMessage construct(str _message = '', VKMessageFormat _messageFormat = VKMessageFormat::Xml)
    {
        VKMessage   message;
 
        switch (_messageFormat)
        {
            case VKMessageFormat::Xml:
                message = new VKMessageXml();
                break;
            default:
                throw error(strFmt("%1: Unknown message format.", funcName()));
        }
 
        message.initFromMessage(_message);
 
        return message;
    }

}

XML wrapper:
/// <summary>
/// XML message implementation
/// </summary>
class VKMessageXml extends VKMessage
{
    System.Xml.XmlDocument          doc;
    System.Xml.XmlElement           selectedElement;
    System.Xml.XmlNodeList          nodeList;
    int                             currentIndex;
    System.Xml.XmlNamespaceManager  nsmgr;

    /// <summary>
    /// Adds XML namespace
    /// </summary>
    /// <param name = "_nameSpace">name space</param>
    /// <param name = "_nameSpaceUrl">name space URL</param>
    public void addNamespace(str _nameSpace, str _nameSpaceUrl)
    {
        if (!nsmgr)
        {
            nsmgr = new System.Xml.XmlNamespaceManager(doc.NameTable);
        }
        nsmgr.AddNamespace(_nameSpace, _nameSpaceUrl);
    }

    public VKMessage createNode(str _name, str _value = '', boolean _append = true)
    {
        VKMessageXml           message;
        System.Xml.XmlElement   createdElement;
 
        createdElement = doc.CreateElement(_name);
 
        if (_value)
        {
            createdElement.AppendChild(doc.CreateTextNode(_value));
        }
 
        if (_append)
        {
            if (selectedElement)
            {
                selectedElement.AppendChild(createdElement);
            }
            else
            {
                doc.AppendChild(createdElement);
            }
        }
 
        message = new VKMessageXml();
        message.initFromObject(doc, createdElement);
 
        return message;
    }

    public VKMessage getDocument()
    {
        VKMessageXml message = new VKMessageXml();
 
        message.initFromObject(doc, null);
 
        return message;
    }

    public str getDocumentContent()
    {
        return doc.get_OuterXml();
    }

    public VKMessage getNextNode()
    {
        VKMessageXml   message;
        int             elements;
 
        if (nodeList)
        {
            elements = nodeList.get_Count();
        }
 
        if (elements && elements > currentIndex)
        {
            message = new VKMessageXml();
            message.initFromObject(doc, nodeList.get_ItemOf(currentIndex));
            currentIndex++;
        }
 
        return message;
    }

    public int getNodeCount()
    {
        int nodeCount = 0;
        if (nodeList)
        {
            nodeCount = nodeList.get_Count();
        }
        return nodeCount;
    }

    public str getValue()
    {
        if (selectedElement)
        {
            return selectedElement.get_InnerText();
        }
        return '';
    }

    public void initFromMessage(str _message)
    {
        System.Xml.XmlException xmlError;
        System.Exception        ex;
        System.String           errorMsg;
        str                     error;
 
        doc = new System.Xml.XmlDocument();
        doc.set_PreserveWhitespace(true);
        if (_message)
        {
            try
            {
                doc.LoadXml(_message);
            }
            catch (Exception::CLRError)
            {
                ex = CLRInterop::getLastException();
                if (null != ex)
                {
                    xmlError    = ex.get_InnerException();
                    if (null != xmlError)
                    {
                        errorMsg    = xmlError.get_Message();
                        error       = errorMsg;
                    }
                }
                throw error(strFmt("%1. XML Error: %2.", funcName(), error));
            }
        }
    }

    /// <summary>
    /// Init from System.Xml.XmlDocument object
    /// </summary>
    /// <param name = "_doc">XmlDocument document</param>
    /// <param name = "_selectedElement">selected element</param>
    protected void initFromObject(System.Xml.XmlDocument _doc, System.Xml.XmlElement _selectedElement)
    {
        doc             = _doc;
        selectedElement = _selectedElement;
    }

    public VKMessage selectNode(str _name, boolean _returnEmptyIfNone = false)
    {
        VKMessageXml   message;
        int             nCount;
  
        currentIndex = 0;
        if (selectedElement)
        {
            if (nsmgr)
            {
                nodeList = selectedElement.SelectNodes(_name, nsmgr);
            }
            else
            {
                nodeList = selectedElement.SelectNodes(_name);
            }
        }
        else
        {
            if (nsmgr)
            {
                nodeList = doc.SelectNodes(_name, nsmgr);
            }
            else
            {
                nodeList = doc.SelectNodes(_name);
            }
        }
  
        nCount = nodeList.get_Count();
        if (nCount)
        {
            message = new VKMessageXml();
            message.initFromObject(doc, nodeList.get_ItemOf(0));
        }
        else if (_returnEmptyIfNone)
        {
            message = new VKMessageXml();
            message.initFromObject(doc, null);
        }
  
        return message;
    }

}


 

Search

About

DaxOnline.org is free platform that allows you to quickly store and reuse snippets, notes, articles related to Dynamics AX.

Authors are allowed to set their own AdSense units and "buy me a coffee" link.
Join us.

Blog Tags