[ONOS-5884]YANG Serializer: Implement XML serializer.

Change-Id: Idffda88938d9c6c7b7c7814127a340bd2dc35039
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/DataNodeXmlListener.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/DataNodeXmlListener.java
new file mode 100644
index 0000000..4b13bbe
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/DataNodeXmlListener.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.dom4j.Element;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.KeyLeaf;
+import org.onosproject.yang.model.LeafNode;
+import org.onosproject.yang.model.ListKey;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaId;
+import org.onosproject.yang.runtime.Annotation;
+import org.onosproject.yang.runtime.helperutils.DataNodeListener;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * Represents implementation of data node listener.
+ */
+class DataNodeXmlListener implements DataNodeListener {
+
+    /**
+     * Stack for element is maintained for hierarchical references, this is
+     * used during data node walker and preparation of XML.
+     */
+    private final Stack<Element> elementStack = new Stack<>();
+
+    /**
+     * Root element of XML.
+     */
+    private Element rootElement;
+
+    /**
+     * XML string for data node.
+     */
+    private String xmlData = EMPTY_STRING;
+
+    /**
+     * Annotation map used to search list of annotations associated with
+     * resource id.
+     */
+    private Map<ResourceId, List<Annotation>> annotationMap;
+
+    /**
+     * Resource id builder.
+     */
+    private ResourceId.Builder rIdBuilder;
+
+    private static final String FORWARD_SLASH = "/";
+    private static final String EMPTY_STRING = "";
+
+    /**
+     * Creates a new data node XML serializer listener.
+     *
+     * @param annotations annotation map with resource id as key
+     * @param ridBuilder  resource id builder
+     */
+    DataNodeXmlListener(Map<ResourceId, List<Annotation>> annotations,
+                        ResourceId.Builder ridBuilder) {
+        annotationMap = annotations;
+        rIdBuilder = ridBuilder;
+    }
+
+    /**
+     * Sets the root XML element.
+     *
+     * @param rootElement root element
+     */
+    public void rootElement(Element rootElement) {
+        this.rootElement = rootElement;
+    }
+
+    /**
+     * Returns XML string.
+     *
+     * @return XML string
+     */
+    public String xmlData() {
+        return xmlData;
+    }
+
+    @Override
+    public void enterDataNode(DataNode node) {
+        if (!isRootDataNode(node)) {
+            SerializerHandlerFactory factory = SerializerHandlerFactory.instance();
+            XmlSerializerHandler handler =
+                    factory.getSerializerHandlerForContext(node);
+            try {
+                if (handler != null) {
+                    Element element = handler.processXmlContext(node,
+                                                                elementStack);
+                    if (elementStack.isEmpty()) {
+                        rootElement(element);
+                    }
+                    elementStack.push(element);
+
+                    // search in map whether there is entry for this resource id
+                    ResourceId id = getResourceId(node);
+                    List<Annotation> annotations = annotationMap.get(id);
+
+                    /**
+                     * If there is annotations for given resource id then get
+                     * list of annotations and add as attribute
+                     */
+                    if (annotations != null) {
+                        for (Annotation annotation : annotations) {
+                            element.addAttribute(annotation.name(),
+                                                 annotation.value());
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                throw new XmlSerializerException(e.getMessage());
+            }
+
+            if (handler != null) {
+                handler.setXmlValue(node, elementStack);
+            }
+        }
+    }
+
+    @Override
+    public void exitDataNode(DataNode dataNode) {
+        if (!elementStack.isEmpty() &&
+                elementStack.peek().equals(rootElement)) {
+            xmlData = xmlData + rootElement.asXML();
+        }
+
+        if (!isRootDataNode(dataNode)) {
+            elementStack.pop();
+            rIdBuilder.removeLastKey();
+        }
+    }
+
+    /**
+     * Returns resource id for the data node.
+     *
+     * @param dataNode data node
+     * @return resource id for the data node
+     */
+    private ResourceId getResourceId(DataNode dataNode) {
+        SchemaId schemaId = dataNode.key().schemaId();
+        switch (dataNode.type()) {
+            case MULTI_INSTANCE_LEAF_VALUE_NODE:
+                Object valObject = ((LeafNode) dataNode).value();
+                rIdBuilder = rIdBuilder.addLeafListBranchPoint(schemaId.name(),
+                                                               schemaId.namespace(),
+                                                               valObject);
+                break;
+            case MULTI_INSTANCE_NODE:
+                rIdBuilder = rIdBuilder.addBranchPointSchema(schemaId.name(),
+                                                             schemaId.namespace());
+                NodeKey key = dataNode.key();
+                if (key instanceof ListKey) {
+                    List<KeyLeaf> keyLeaves = ((ListKey) key).keyLeafs();
+                    if (keyLeaves != null) {
+                        for (KeyLeaf keyLeaf : keyLeaves) {
+                            SchemaId leafSchema = keyLeaf.leafSchema();
+                            rIdBuilder = rIdBuilder.addKeyLeaf(leafSchema.name(),
+                                                               leafSchema.namespace(),
+                                                               keyLeaf.leafValue());
+                        }
+                    }
+                }
+                break;
+            case SINGLE_INSTANCE_LEAF_VALUE_NODE:
+            case SINGLE_INSTANCE_NODE:
+                rIdBuilder = rIdBuilder.addBranchPointSchema(schemaId.name(),
+                                                             schemaId.namespace());
+                break;
+            default:
+                throw new XmlSerializerException("Unsupported type" +
+                                                         dataNode.type());
+        }
+        return rIdBuilder.build();
+    }
+
+    /**
+     * Returns true if it is root data node.
+     *
+     * @param node data node
+     * @return true if it is root data node, false otherwise
+     */
+    private static boolean isRootDataNode(DataNode node) {
+        return node.key().schemaId().name().equals(FORWARD_SLASH);
+    }
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/DefaultXmlWalker.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/DefaultXmlWalker.java
new file mode 100644
index 0000000..1623aed
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/DefaultXmlWalker.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.dom4j.Element;
+
+import java.util.Iterator;
+
+import static org.onosproject.yang.serializers.xml.XmlNodeType.OBJECT_NODE;
+import static org.onosproject.yang.serializers.xml.XmlNodeType.TEXT_NODE;
+
+/**
+ * Represents implementation of xml walker.
+ */
+public class DefaultXmlWalker implements XmlWalker {
+
+    @Override
+    public void walk(XmlListener listener, Element element,
+                     Element rootElement) {
+        try {
+
+            listener.enterXmlElement(element, getElementType(element),
+                                     rootElement);
+
+            if (element.hasContent() && !element.isTextOnly()) {
+                Iterator i = element.elementIterator();
+                while (i.hasNext()) {
+                    Element childElement = (Element) i.next();
+                    walk(listener, childElement, rootElement);
+                }
+            }
+
+            listener.exitXmlElement(element, getElementType(element),
+                                    rootElement);
+        } catch (Exception e) {
+            throw new XmlSerializerException(e.getMessage());
+        }
+    }
+
+    /**
+     * Determine the type of an element.
+     *
+     * @param element to be analysed
+     * @return type of the element
+     */
+    private XmlNodeType getElementType(Element element) {
+        Element newElement = element.createCopy();
+        newElement.remove(element.getNamespace());
+        return newElement.hasContent() && newElement.isTextOnly() ?
+                TEXT_NODE : OBJECT_NODE;
+    }
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/SerializerHandlerFactory.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/SerializerHandlerFactory.java
new file mode 100644
index 0000000..eb6199e
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/SerializerHandlerFactory.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+
+import org.onosproject.yang.model.DataNode;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_NODE;
+
+/**
+ * Represents an xml serializer handle factory to create different types of
+ * data node.
+ */
+public final class SerializerHandlerFactory {
+
+    /**
+     * Map of xml codec handler.
+     */
+    private final Map<DataNode.Type, XmlSerializerHandler> handlerMap;
+
+    /**
+     * Creates a new codec handler factory.
+     */
+    private SerializerHandlerFactory() {
+        handlerMap = new HashMap<>();
+        handlerMap.put(SINGLE_INSTANCE_NODE,
+                       new XmlSerializerNodeHandler());
+        handlerMap.put(MULTI_INSTANCE_NODE,
+                       new XmlSerializerNodeHandler());
+        handlerMap.put(SINGLE_INSTANCE_LEAF_VALUE_NODE,
+                       new XmlSerializerLeafHandler());
+        handlerMap.put(MULTI_INSTANCE_LEAF_VALUE_NODE,
+                       new XmlSerializerLeafHandler());
+    }
+
+    /**
+     * Returns serializer instance handler node instance.
+     *
+     * @param node data node
+     * @return returns serializer handler node instance
+     */
+    public XmlSerializerHandler getSerializerHandlerForContext(
+            DataNode node) {
+        XmlSerializerHandler handler = handlerMap.get(node.type());
+        if (handler == null) {
+            throw new XmlSerializerException("Unsupported node type " + node
+                    .type());
+        }
+        return handler;
+    }
+
+    /*
+     * Bill Pugh Singleton pattern. INSTANCE won't be instantiated until the
+     * LazyHolder class is loaded via a call to the instance() method below.
+     */
+    private static class LazyHolder {
+        private static final SerializerHandlerFactory INSTANCE =
+                new SerializerHandlerFactory();
+    }
+
+    /**
+     * Returns a reference to the Singleton Codec Handler factory.
+     *
+     * @return the singleton codec handler factory
+     */
+    public static SerializerHandlerFactory instance() {
+        return LazyHolder.INSTANCE;
+    }
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlListener.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlListener.java
new file mode 100644
index 0000000..3f1b466
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlListener.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.dom4j.Element;
+
+/**
+ * Abstraction of an entity which provide call back methods which are called
+ * by xml walker while walking the xml data tree. This interface needs to be
+ * implemented by protocol implementing listener's based call backs while
+ * xml walk.
+ */
+interface XmlListener {
+
+    /**
+     * Callback invoked during a node entry. All the related information
+     * about the node can be obtained from the element.
+     *
+     * @param element     current xml node(element)
+     * @param nodeType    xml node type
+     * @param rootElement root element
+     */
+    void enterXmlElement(Element element, XmlNodeType nodeType,
+                         Element rootElement);
+
+    /**
+     * Callback invoked during a node exit. All the related information
+     * about the node can be obtained from the element.
+     *
+     * @param element     current xml node(element)
+     * @param nodeType    xml node type
+     * @param rootElement root element
+     */
+    void exitXmlElement(Element element, XmlNodeType nodeType,
+                        Element rootElement);
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlNodeType.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlNodeType.java
new file mode 100644
index 0000000..eb70c17
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlNodeType.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+/**
+ * Represents type of node in xml data tree.
+ */
+enum XmlNodeType {
+
+    /**
+     * An object node has at least one child node.
+     */
+    OBJECT_NODE,
+
+    /**
+     * A text node has no child node, and has a text value.
+     */
+    TEXT_NODE
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializer.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializer.java
new file mode 100644
index 0000000..5872e51
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializer.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.apache.commons.io.IOUtils;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.Annotation;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.CompositeStream;
+import org.onosproject.yang.runtime.DefaultCompositeData;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+import org.onosproject.yang.runtime.DefaultResourceData;
+import org.onosproject.yang.runtime.YangSerializer;
+import org.onosproject.yang.runtime.YangSerializerContext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import static org.onosproject.yang.runtime.helperutils.DefaultDataNodeWalker.walk;
+import static org.onosproject.yang.runtime.helperutils.SerializerHelper.initializeDataNode;
+import static org.onosproject.yang.runtime.helperutils.SerializerHelper.initializeResourceId;
+import static org.onosproject.yang.serializers.utils.SerializersUtil.addRootElementWithAnnotation;
+import static org.onosproject.yang.serializers.utils.SerializersUtil.convertRidToUri;
+import static org.onosproject.yang.serializers.utils.SerializersUtil.convertUriToRid;
+
+/**
+ * Represents an implementation of XML serializer.
+ */
+public class XmlSerializer implements YangSerializer {
+    private static final String XML = "xml";
+
+    @Override
+    public String supportsFormat() {
+        return XML;
+    }
+
+    @Override
+    public CompositeData decode(CompositeStream external,
+                                YangSerializerContext context) {
+
+        try {
+            //parse XML input
+            String xmlInput = addRootElementWithAnnotation(
+                    external.resourceData(), context.getProtocolAnnotations());
+            Document document = DocumentHelper.parseText(xmlInput);
+
+            // initialize all the required builders
+            CompositeData.Builder cBuilder = DefaultCompositeData.builder();
+            ResourceData.Builder rdBuilder = DefaultResourceData.builder();
+            XmlWalker walker = new DefaultXmlWalker();
+            XmlSerializerListener listener = new XmlSerializerListener();
+            listener.cBuilder(cBuilder);
+
+            String uri = external.resourceId();
+            if (uri == null) {
+                listener.dnBuilder(initializeDataNode(context));
+                walker.walk(listener, document.getRootElement(),
+                            document.getRootElement());
+                rdBuilder = rdBuilder.addDataNode(listener.dnBuilder().build());
+            } else {
+                /*
+                 * If URI is not null, then each first level elements is
+                 * converted to data node and added to list of data nodes in
+                 * resource data
+                 */
+                ResourceId.Builder rIdBuilder = convertUriToRid(uri, context);
+                Element rootElement = document.getRootElement();
+                if (rootElement.hasContent() && !rootElement.isTextOnly()) {
+                    Iterator i = rootElement.elementIterator();
+                    while (i.hasNext()) {
+                        Element childElement = (Element) i.next();
+                        listener.dnBuilder(initializeDataNode(rIdBuilder));
+                        walker.walk(listener, childElement, rootElement);
+                        rdBuilder = rdBuilder.addDataNode(listener.dnBuilder()
+                                                                  .build());
+                    }
+                }
+                rdBuilder.resourceId(rIdBuilder.build());
+            }
+            return cBuilder.resourceData(rdBuilder.build()).build();
+        } catch (DocumentException e) {
+            throw new XmlSerializerException(e.getMessage());
+        } catch (IOException e) {
+            throw new XmlSerializerException(e.getMessage());
+        }
+    }
+
+    @Override
+    public CompositeStream encode(CompositeData internal,
+                                  YangSerializerContext context) {
+        String uriString = null;
+        ResourceId.Builder builder;
+
+        ResourceId resourceId = internal.resourceData().resourceId();
+        if (resourceId != null) {
+            uriString = convertRidToUri(resourceId);
+            try {
+                builder = resourceId.copyBuilder();
+            } catch (CloneNotSupportedException e) {
+                throw new XmlSerializerException(e.getMessage());
+            }
+        } else {
+            /*
+             * If resource id is null, initialise resource id with context
+             * and get the resource id builder. Resource id is built for each
+             * data node and checked in annotation map for annotations
+             * associated with resource id.
+             */
+            builder = initializeResourceId(context);
+        }
+
+        // Store annotations in map with resource id as key
+        Map<ResourceId, List<Annotation>> annotations = new HashMap<>();
+        List<AnnotatedNodeInfo> annotationList = internal.annotatedNodesInfo();
+        if (annotationList != null) {
+            for (AnnotatedNodeInfo annotationInfo : annotationList) {
+                annotations.put(annotationInfo.resourceId(),
+                                annotationInfo.annotations());
+            }
+        }
+
+        // Walk through data node and build the XML
+        List<DataNode> dataNodes = internal.resourceData().dataNodes();
+        StringBuilder sb = new StringBuilder();
+        for (DataNode dataNode : dataNodes) {
+            DataNodeXmlListener listener = new DataNodeXmlListener(annotations,
+                                                                   builder);
+            walk(listener, dataNode);
+            sb.append(listener.xmlData());
+        }
+
+        // convert XML to input stream and build composite stream
+        InputStream inputStream = IOUtils.toInputStream(sb.toString());
+        return new DefaultCompositeStream(uriString, inputStream);
+    }
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerException.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerException.java
new file mode 100644
index 0000000..b543519
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerException.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+/**
+ * Represents base class for exceptions in XML serializer operations.
+ */
+public class XmlSerializerException extends RuntimeException {
+    private static final long serialVersionUID = 20160211L;
+
+    /**
+     * Creates a new XML serializer exception.
+     */
+    public XmlSerializerException() {
+    }
+
+    /**
+     * Creates a new XML serializer exception with given message.
+     *
+     * @param message the detail of exception in string
+     */
+    public XmlSerializerException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates a new XML serializer exception from given message and cause.
+     *
+     * @param message the detail of exception in string
+     * @param cause   underlying cause of the error
+     */
+    public XmlSerializerException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Creates a new XML serializer exception from cause.
+     *
+     * @param cause underlying cause of the error
+     */
+    public XmlSerializerException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerHandler.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerHandler.java
new file mode 100644
index 0000000..5f706ac
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerHandler.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.dom4j.Namespace;
+import org.onosproject.yang.model.DataNode;
+
+import java.util.Stack;
+
+/**
+ * Represents an serializer handler to process the XML content and add
+ * element to the stack.
+ */
+public abstract class XmlSerializerHandler {
+
+    /**
+     * Sets the namespace and tag name in element tree maintained in stack.
+     *
+     * @param elementStack element tree stack
+     */
+    Element processXmlContext(DataNode dataNode,
+                              Stack<Element> elementStack) {
+
+        Element newElement = updateNameAndNamespace(dataNode,
+                                                    elementStack);
+        return newElement;
+    }
+
+    /**
+     * Returns the new element name by updating tag name and namespace.
+     *
+     * @param node YDT context node
+     * @return new element name by updating tag name and namespace
+     */
+    Element updateNameAndNamespace(DataNode node,
+                                   Stack<Element> elementStack) {
+        String nameSpace = null;
+        String name = null;
+        if (node.key() != null && node.key().schemaId() != null) {
+            nameSpace = node.key().schemaId().namespace();
+            name = node.key().schemaId().name();
+        }
+
+        if (elementStack.isEmpty()) {
+            Element rootElement = DocumentHelper.createDocument()
+                    .addElement(name);
+            if (nameSpace != null) {
+                rootElement.add(Namespace.get(nameSpace));
+            }
+            return rootElement;
+        } else {
+            /*
+             * If element stack is not empty then root element is already
+             * created.
+             */
+            Element xmlElement = elementStack.peek();
+            Element newElement;
+            if (nameSpace != null) {
+                newElement = xmlElement.addElement(name,
+                                                   nameSpace);
+            } else {
+                newElement = xmlElement.addElement(name);
+            }
+            return newElement;
+        }
+    }
+
+    /**
+     * Sets the leaf value in the current element maintained in stack.
+     * Default behaviour is to do nothing.
+     *
+     * @param domElementStack current element node in the stack
+     * @param dataNode        data node
+     */
+    public void setXmlValue(DataNode dataNode,
+                            Stack<Element> domElementStack) {
+    }
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerLeafHandler.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerLeafHandler.java
new file mode 100644
index 0000000..cdde0f6
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerLeafHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.dom4j.Element;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.LeafNode;
+
+import java.util.Stack;
+
+/**
+ * Represents a leaf node handler in XML serializer.
+ */
+public class XmlSerializerLeafHandler extends XmlSerializerHandler {
+
+    @Override
+    public void setXmlValue(DataNode node, Stack<Element> elementStack) {
+        Object value = ((LeafNode) node).value();
+        if (value != null) {
+            elementStack.peek().setText(value.toString());
+        }
+    }
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerListener.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerListener.java
new file mode 100644
index 0000000..b062ac9
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerListener.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.dom4j.Element;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.helperutils.HelperContext;
+
+import static org.onosproject.yang.runtime.helperutils.SerializerHelper.addDataNode;
+import static org.onosproject.yang.runtime.helperutils.SerializerHelper.exitDataNode;
+import static org.onosproject.yang.runtime.helperutils.SerializerHelper.getResourceId;
+import static org.onosproject.yang.serializers.utils.SerializersUtil.convertXmlAttributesToAnnotations;
+import static org.onosproject.yang.serializers.xml.XmlNodeType.OBJECT_NODE;
+import static org.onosproject.yang.serializers.xml.XmlNodeType.TEXT_NODE;
+
+/**
+ * Default implementation of XML listener.
+ */
+class XmlSerializerListener implements XmlListener {
+
+    /**
+     * Data node builder.
+     */
+    private DataNode.Builder dnBuilder;
+
+    /**
+     * Composite data builder.
+     */
+    private CompositeData.Builder cBuilder;
+
+    /**
+     * Sets the data node builder.
+     *
+     * @param builder data node builder
+     */
+    void dnBuilder(DataNode.Builder builder) {
+        dnBuilder = builder;
+    }
+
+    /**
+     * Returns data node builder.
+     *
+     * @return data node builder
+     */
+    DataNode.Builder dnBuilder() {
+        return dnBuilder;
+    }
+
+    /**
+     * Sets the composite data node builder.
+     *
+     * @return composite data builder
+     */
+    public CompositeData.Builder cBuilder() {
+        return cBuilder;
+    }
+
+    /**
+     * Returns composite data builder.
+     *
+     * @return composite data builder
+     */
+    public void cBuilder(CompositeData.Builder cBuilder) {
+        this.cBuilder = cBuilder;
+    }
+
+
+    @Override
+    public void enterXmlElement(Element element, XmlNodeType nodeType,
+                                Element rootElement) {
+
+        // root element should not be added to data node
+        if (element.equals(rootElement)) {
+            return;
+        }
+
+        if (nodeType == OBJECT_NODE && element.content() == null ||
+                element.content().isEmpty()) {
+            nodeType = TEXT_NODE;
+        }
+
+        if (nodeType == OBJECT_NODE) {
+            if (dnBuilder != null) {
+                dnBuilder = addDataNode(dnBuilder, element.getName(),
+                                        element.getNamespace().getURI(),
+                                        null, null);
+            }
+        } else if (nodeType == TEXT_NODE) {
+            if (dnBuilder != null) {
+                dnBuilder = addDataNode(dnBuilder, element.getName(),
+                                        element.getNamespace().getURI(),
+                                        element.getText(), null);
+            }
+        }
+    }
+
+    @Override
+    public void exitXmlElement(Element element, XmlNodeType nodeType,
+                               Element rootElement) {
+        // Ignore the root element as it is not added to data node
+        if (element.equals(rootElement)) {
+            return;
+        }
+
+        // Build resource Id for annotations
+        ResourceId id = getResourceId(dnBuilder);
+        AnnotatedNodeInfo annotatedNodeInfo =
+                convertXmlAttributesToAnnotations(element, id);
+        if (annotatedNodeInfo != null) {
+            cBuilder.addAnnotatedNodeInfo(annotatedNodeInfo);
+        }
+
+        /*
+         * Since we need to build data node from top node, we should not
+         * traverse back to parent for top node.
+         */
+        HelperContext info = (HelperContext) dnBuilder.appInfo();
+        if (info.getParentResourceIdBldr() == null) {
+            dnBuilder = exitDataNode(dnBuilder);
+        }
+    }
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerNodeHandler.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerNodeHandler.java
new file mode 100644
index 0000000..0ae3539
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlSerializerNodeHandler.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+/**
+ * Represents a single instance node and multi instance node handler.
+ */
+public class XmlSerializerNodeHandler extends XmlSerializerHandler {
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlWalker.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlWalker.java
new file mode 100644
index 0000000..81c920a
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/XmlWalker.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.dom4j.Element;
+
+/**
+ * Abstraction of an entity which provides interfaces for XML walk.
+ * This interface serve as common tools for anyone who needs to parse the XML
+ * node with depth-first algorithm.
+ */
+interface XmlWalker {
+
+    /**
+     * Walks the XML data tree. Protocols implements XML listener service
+     * and walks XML tree with input as implemented object. XML walker provides
+     * call backs to implemented methods.
+     *
+     * @param listener    XML listener implemented by the protocol
+     * @param walkElement node(element) of the XML data tree
+     * @param rootElement root node(element) of the XML data tree
+     */
+    void walk(XmlListener listener, Element walkElement,
+              Element rootElement);
+}
diff --git a/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/package-info.java b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/package-info.java
new file mode 100644
index 0000000..43b4abc
--- /dev/null
+++ b/serializers/xml/src/main/java/org/onosproject/yang/serializers/xml/package-info.java
@@ -0,0 +1,20 @@
+/*
+ *  Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The XML serializer implementation of the YangSerializer interface.
+ */
+package org.onosproject.yang.serializers.xml;
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
new file mode 100644
index 0000000..138d22d
--- /dev/null
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.onosproject.yang.YangModel;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.runtime.AppModuleInfo;
+import org.onosproject.yang.runtime.DefaultAppModuleInfo;
+import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
+import org.onosproject.yang.runtime.ModelRegistrationParam;
+import org.onosproject.yang.runtime.YangModelRegistry;
+import org.onosproject.yang.runtime.ymrimpl.DefaultYangModelRegistry;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.deSerializeDataModel;
+import static org.onosproject.yang.compiler.plugin.utils.YangApacheUtils.processModuleId;
+import static org.onosproject.yang.compiler.plugin.utils.YangApacheUtils.processYangModel;
+import static org.onosproject.yang.compiler.utils.UtilConstants.TEMP;
+import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.deleteDirectory;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getInterfaceClassName;
+
+/**
+ * Represents mock bundle context. provides bundle context for YSR to do unit
+ * testing.
+ */
+public class MockYangSchemaNodeProvider {
+
+    private static final String FS = File.separator;
+    private static final String PATH = System.getProperty("user.dir") +
+            FS + "target" + FS + "classes" + FS;
+    private static final String SER_FILE_PATH = "yang" + FS + "resources" +
+            FS + "YangMetaData.ser";
+    private static final String META_PATH = PATH + SER_FILE_PATH;
+    private static final String TEMP_FOLDER_PATH = PATH + TEMP;
+    private YangModelRegistry reg = new DefaultYangModelRegistry();
+    private List<YangNode> nodes = new ArrayList<>();
+
+    /**
+     * Creates an instance of mock bundle context.
+     */
+    public MockYangSchemaNodeProvider() {
+    }
+
+    /**
+     * Process YANG schema node for a application.
+     */
+    public void processSchemaRegistry() {
+        try {
+            //Need to deserialize generated meta data file for unit tests.
+            Set<YangNode> appNode = deSerializeDataModel(META_PATH);
+            nodes.addAll(appNode);
+            reg.registerModel(prepareParam(nodes));
+            deleteDirectory(TEMP_FOLDER_PATH);
+        } catch (IOException e) {
+        }
+    }
+
+    /**
+     * Unregister given nodes from runtime service.
+     *
+     * @param nodes list of nodes
+     */
+    public void unRegister(List<YangNode> nodes) {
+        reg.unregisterModel(prepareParam(nodes));
+    }
+
+    /**
+     * Prepares model registration parameter.
+     *
+     * @param nodes list of nodes
+     * @return model registration parameter
+     */
+    private ModelRegistrationParam prepareParam(List<YangNode> nodes) {
+        //Process loading class file.
+        String appName;
+        ClassLoader classLoader = getClass().getClassLoader();
+
+        //Create model registration param.
+        ModelRegistrationParam.Builder b =
+                DefaultModelRegistrationParam.builder();
+
+        //create a new YANG model
+        YangModel model = processYangModel(META_PATH, nodes);
+        //set YANG model
+        b.setYangModel(model);
+
+        Iterator<YangNode> it = nodes.iterator();
+        while (it.hasNext()) {
+            YangSchemaNode node = it.next();
+
+            //If service class is not generated then use
+            // interface file to load this class.
+            appName = getInterfaceClassName(node);
+            Class<?> cls;
+            try {
+                cls = classLoader.loadClass(appName);
+            } catch (ClassNotFoundException e) {
+                continue;
+            }
+
+            //generate app info.
+            AppModuleInfo info = new DefaultAppModuleInfo(cls, null);
+            b.addAppModuleInfo(processModuleId((YangNode) node), info);
+        }
+        return b.build();
+    }
+
+    /**
+     * Returns schema registry.
+     *
+     * @return schema registry
+     */
+    public DefaultYangModelRegistry registry() {
+        return (DefaultYangModelRegistry) reg;
+    }
+}
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java
new file mode 100644
index 0000000..dfc8d06
--- /dev/null
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.onosproject.yang.model.SchemaContext;
+import org.onosproject.yang.runtime.Annotation;
+import org.onosproject.yang.runtime.DefaultAnnotation;
+import org.onosproject.yang.runtime.YangSerializerContext;
+import org.onosproject.yang.runtime.ymrimpl.DefaultYangModelRegistry;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Tests the default schema context provider methods.
+ */
+public class MockYangSerializerContext implements YangSerializerContext {
+
+    private static MockYangSchemaNodeProvider schemaProvider =
+            new MockYangSchemaNodeProvider();
+    private static final String NETCONF_NS =
+            "urn:ietf:params:xml:ns:netconf:base:1.0";
+    private static final String XMNLS_NC = "xmlns:xc";
+
+
+    @Override
+    public SchemaContext getContext() {
+        schemaProvider.processSchemaRegistry();
+        DefaultYangModelRegistry registry = schemaProvider.registry();
+        return registry;
+    }
+
+    @Override
+    public List<Annotation> getProtocolAnnotations() {
+        Annotation annotation = new DefaultAnnotation(XMNLS_NC, NETCONF_NS);
+        List<Annotation> protocolAnnotation = new LinkedList<>();
+        protocolAnnotation.add(annotation);
+        return protocolAnnotation;
+    }
+}
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/XmlSerializerTest.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/XmlSerializerTest.java
new file mode 100644
index 0000000..1f53ac5
--- /dev/null
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/XmlSerializerTest.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.InnerNode;
+import org.onosproject.yang.model.LeafListKey;
+import org.onosproject.yang.model.LeafNode;
+import org.onosproject.yang.model.ListKey;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.SchemaId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.Annotation;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.CompositeStream;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+import org.onosproject.yang.runtime.YangSerializer;
+import org.onosproject.yang.runtime.YangSerializerContext;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+/**
+ *
+ */
+public class XmlSerializerTest {
+
+    private static YangSerializerContext context;
+    private static YangSerializer xmlSerializer;
+
+    @BeforeClass
+    public static void prepare() {
+        context = new MockYangSerializerContext();
+        xmlSerializer = new XmlSerializer();
+    }
+
+    /**
+     * Validates data node in which XML element is of type YANG container.
+     */
+    @Test
+    public void testContainer() {
+        String path = "src/test/resources/testContainer.xml";
+
+        DefaultCompositeStream external =
+                new DefaultCompositeStream(null, parseInput(path));
+        CompositeData compositeData = xmlSerializer.decode(external, context);
+        DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+        DataNode food = validateContainerDataNode(rootNode, "food", "yrt:food");
+        validateLeafDataNode(food, "p1", "yrt:food", "p1_value");
+        validateLeafListDataNode(food, "p2", "yrt:food", "p2_value");
+        validateLeafListDataNode(food, "p2", "yrt:food", "p2_value1");
+        DataNode c2 = validateContainerDataNode(rootNode, "c2", "yrt:food");
+        validateLeafDataNode(c2, "p3", "yrt:food", "p3_value");
+
+        // encode test
+        CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+                                                               context);
+        InputStream inputStream = compositeStream.resourceData();
+        assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+    }
+
+    /**
+     * Validates data node in which XML element is of type YANG leaf.
+     */
+    @Test
+    public void testModuleLevelLeaf() {
+        String path = "src/test/resources/testModuleLevelLeaf.xml";
+
+        DefaultCompositeStream external =
+                new DefaultCompositeStream(null, parseInput(path));
+        CompositeData compositeData = xmlSerializer.decode(external, context);
+        DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+        validateLeafDataNode(rootNode, "bool", "yrt:food", "true");
+
+        // encode test
+        CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+                                                               context);
+        InputStream inputStream = compositeStream.resourceData();
+        assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+    }
+
+    /**
+     * Validates data node in which XML element is of type YANG list.
+     */
+    @Test
+    public void testListWithKeyleaves() {
+        String path = "src/test/resources/testListWithKeyleaves.xml";
+        DefaultCompositeStream external =
+                new DefaultCompositeStream(null, parseInput(path));
+        CompositeData compositeData = xmlSerializer.decode(external, context);
+        DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+        List<String> keyNames = new LinkedList<>();
+        keyNames.add("k1");
+        keyNames.add("k2");
+        keyNames.add("k3");
+
+        List<String> keyNs = new LinkedList<>();
+        keyNs.add("yrt:list");
+        keyNs.add("yrt:list");
+        keyNs.add("yrt:list");
+
+        List<Object> values = new LinkedList<>();
+        values.add("k1_Value");
+        values.add("k2_Value");
+        values.add("k3_Value");
+
+        DataNode listl1 = validateListDataNode(rootNode, "l1", "yrt:list",
+                                               keyNames, keyNs, values);
+        validateLeafDataNode(listl1, "k1", "yrt:list", "k1_Value");
+        validateLeafDataNode(listl1, "k2", "yrt:list", "k2_Value");
+        validateLeafDataNode(listl1, "k3", "yrt:list", "k3_Value");
+        DataNode c1 = validateContainerDataNode(listl1, "c1", "yrt:list");
+        validateLeafDataNode(c1, "leaf_c1", "yrt:list", "l1_value");
+
+        values = new LinkedList<>();
+        values.add("k1_Value1");
+        values.add("k2_Value2");
+        values.add("k3_Value3");
+
+        DataNode listl2 = validateListDataNode(rootNode, "l1", "yrt:list",
+                                               keyNames, keyNs, values);
+        validateLeafDataNode(listl2, "k1", "yrt:list", "k1_Value1");
+        validateLeafDataNode(listl2, "k2", "yrt:list", "k2_Value2");
+        validateLeafDataNode(listl2, "k3", "yrt:list", "k3_Value3");
+        c1 = validateContainerDataNode(listl2, "c1", "yrt:list");
+        validateLeafDataNode(c1, "leaf_c1", "yrt:list", "l1_value1");
+
+        // encode test
+        CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+                                                               context);
+        InputStream inputStream = compositeStream.resourceData();
+        assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+    }
+
+    /**
+     * Validates data node in which XML element is child of YANG
+     * choice-case.
+     */
+    @Test
+    public void testChoiceCase() {
+        String path = "src/test/resources/testChoiceCase.xml";
+
+        DefaultCompositeStream external =
+                new DefaultCompositeStream(null, parseInput(path));
+        CompositeData compositeData = xmlSerializer.decode(external, context);
+        DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+        DataNode list1 = validateListDataNode(rootNode, "banana",
+                                              "yrt:choice-case", null, null, null);
+        validateLeafDataNode(list1, "l1", "yrt:choice-case", "value2");
+        DataNode coldDrink = validateContainerDataNode(rootNode, "cold-drink",
+                                                       "yrt:choice-case");
+        validateLeafListDataNode(coldDrink, "flavor", "yrt:choice-case",
+                                 "value3");
+
+        // encode test
+        CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+                                                               context);
+        InputStream inputStream = compositeStream.resourceData();
+        assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+    }
+
+    /**
+     * Validates data node in which XML element is of YANG augmented nodes.
+     */
+    @Test
+    public void testAugment() {
+        String path = "src/test/resources/testAugment.xml";
+
+        String uri = "urn:ietf:params:xml:ns:yang:yrt-ietf-network:networks/network/node";
+        DefaultCompositeStream external =
+                new DefaultCompositeStream(uri, parseInput(path));
+        CompositeData compositeData = xmlSerializer.decode(external, context);
+        ResourceData resourceData = compositeData.resourceData();
+        List<DataNode> dataNodes = resourceData.dataNodes();
+        DataNode dataNode = dataNodes.get(0);
+        SchemaId schemaId = dataNode.key().schemaId();
+        assertThat(schemaId.name(), is("t-point"));
+        assertThat(schemaId.namespace(), is("urn:ietf:params:xml:ns:yang:yrt-ietf-network-topology"));
+        validateLeafDataNode(dataNode, "tp-id",
+                             "urn:ietf:params:xml:ns:yang:yrt-ietf-network-topology", "Stub");
+
+        // encode test
+        CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+                                                               context);
+        InputStream inputStream = compositeStream.resourceData();
+        assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+    }
+
+    /**
+     * Validates data node in which XML element is child of YANG grouping.
+     */
+    @Test
+    public void testGroupingUsesDataNode() {
+        String path = "src/test/resources/testGroupingUses.xml";
+
+        String uri = "urn:ietf:params:xml:ns:yang:yrt-ietf-network:networks-state/network";
+        DefaultCompositeStream external =
+                new DefaultCompositeStream(uri, parseInput(path));
+        CompositeData compositeData = xmlSerializer.decode(external, context);
+        ResourceData resourceData = compositeData.resourceData();
+        List<DataNode> dataNodes = resourceData.dataNodes();
+        LeafNode dataNode = ((LeafNode) dataNodes.get(0));
+        SchemaId schemaId = dataNode.key().schemaId();
+        assertThat(schemaId.name(), is("network-ref"));
+        assertThat(schemaId.namespace(), is("urn:ietf:params:xml:ns:yang:yrt-ietf-network"));
+        assertThat(dataNode.value().toString(), is("abc"));
+
+        // encode test
+        CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+                                                               context);
+        InputStream inputStream = compositeStream.resourceData();
+        assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+    }
+
+    /**
+     * Validates whether XML attributes is converted to annotations.
+     */
+    @Test
+    public void testXmlAttributes() {
+        String path = "src/test/resources/testXmlAttributes.xml";
+        String namespace = "http://example.com/schema/1.2/config";
+
+        DefaultCompositeStream external =
+                new DefaultCompositeStream(null, parseInput(path));
+        CompositeData compositeData = xmlSerializer.decode(external, context);
+        DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+        DataNode top = validateContainerDataNode(rootNode, "top", namespace);
+        DataNode interfaceDn = validateContainerDataNode(top, "interface",
+                                                         namespace);
+        validateLeafDataNode(interfaceDn, "name", namespace, "Ethernet0/0");
+        validateLeafDataNode(interfaceDn, "mtu", namespace, "1500");
+        DataNode address = validateContainerDataNode(interfaceDn, "address",
+                                                     namespace);
+        validateLeafDataNode(address, "name", namespace, "192.0.2.4");
+        validateLeafDataNode(address, "prefix-length", namespace, "24");
+
+        List<AnnotatedNodeInfo> annotatedNodeInfos = compositeData
+                .annotatedNodesInfo();
+        AnnotatedNodeInfo annotatedNodeInfo = annotatedNodeInfos.get(0);
+        List<Annotation> annotationList = annotatedNodeInfo.annotations();
+        Annotation annotation = annotationList.get(0);
+        assertThat(annotation.name(), is("xc:operation"));
+        assertThat(annotation.value(), is("replace"));
+
+        // encode test
+        CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+                                                               context);
+        InputStream inputStream = compositeStream.resourceData();
+        assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+    }
+
+    /**
+     * Validates and returns container data node.
+     *
+     * @param parent    data node holding container
+     * @param name      name of the container
+     * @param namespace namespace of the container
+     * @return container data node
+     */
+    private static DataNode validateContainerDataNode(DataNode parent,
+                                                      String name,
+                                                      String namespace) {
+        Map<NodeKey, DataNode> childNodes = ((InnerNode) parent).childNodes();
+        NodeKey key = NodeKey.builder().schemaId(name, namespace).build();
+        DataNode dataNode = childNodes.get(key);
+        SchemaId schemaId = dataNode.key().schemaId();
+        assertThat(schemaId.name(), is(name));
+        assertThat(schemaId.namespace(), is(namespace));
+        return dataNode;
+    }
+
+    /**
+     * Validates and returns list data node.
+     *
+     * @param parent    data node holding list
+     * @param name      name of the list
+     * @param namespace namespace of the list
+     * @param keynames  list of key leaf names
+     * @param keyNs     list of key leaf namespace
+     * @param keyVal    list of key leaf values
+     * @return list data node
+     */
+    private static DataNode validateListDataNode(DataNode parent,
+                                                 String name, String namespace,
+                                                 List<String> keynames,
+                                                 List<String> keyNs,
+                                                 List<Object> keyVal) {
+        Map<NodeKey, DataNode> childNodes = ((InnerNode) parent).childNodes();
+        NodeKey key = NodeKey.builder().schemaId(name, namespace).build();
+        DataNode dataNode;
+        if (keynames != null && !keynames.isEmpty()) {
+            ListKey.ListKeyBuilder listKeyBldr = new ListKey.ListKeyBuilder();
+            listKeyBldr.schemaId(key.schemaId());
+            for (int i = 0; i < keynames.size(); i++) {
+                listKeyBldr.addKeyLeaf(keynames.get(i), keyNs.get(i),
+                                       keyVal.get(i));
+            }
+            dataNode = childNodes.get(listKeyBldr.build());
+        } else {
+            dataNode = childNodes.get(key);
+        }
+        SchemaId schemaId = dataNode.key().schemaId();
+        assertThat(schemaId.name(), is(name));
+        assertThat(schemaId.namespace(), is(namespace));
+        return dataNode;
+    }
+
+    /**
+     * Validates leaf data node.
+     *
+     * @param parent    data node holding leaf
+     * @param name      name of the leaf
+     * @param namespace namespace of the leaf
+     * @param value     leaf value
+     */
+    private static void validateLeafDataNode(DataNode parent,
+                                             String name, String namespace,
+                                             Object value) {
+        Map<NodeKey, DataNode> childNodes = ((InnerNode) parent).childNodes();
+        NodeKey key = NodeKey.builder().schemaId(name, namespace).build();
+        LeafNode dataNode = ((LeafNode) childNodes.get(key));
+        SchemaId schemaId = dataNode.key().schemaId();
+        assertThat(schemaId.name(), is(name));
+        assertThat(schemaId.namespace(), is(namespace));
+        assertThat(dataNode.value().toString(), is(value));
+    }
+
+    /**
+     * Validates leaf-list data node.
+     *
+     * @param parent    data node holding leaf-list
+     * @param name      name of the leaf-list
+     * @param namespace namespace of the leaf-list
+     * @param value     leaf-list value
+     */
+    private static void validateLeafListDataNode(DataNode parent,
+                                                 String name, String namespace,
+                                                 Object value) {
+        Map<NodeKey, DataNode> childNodes = ((InnerNode) parent).childNodes();
+        NodeKey key = NodeKey.builder().schemaId(name, namespace).build();
+        LeafListKey.LeafListKeyBuilder leafListBldr =
+                new LeafListKey.LeafListKeyBuilder();
+        leafListBldr.schemaId(key.schemaId());
+        leafListBldr.value(value);
+        DataNode leafListNode = childNodes.get(leafListBldr.build());
+        SchemaId schemaId = leafListNode.key().schemaId();
+        assertThat(schemaId.name(), is(name));
+        assertThat(schemaId.namespace(), is(namespace));
+        assertThat(((LeafNode) leafListNode).value().toString(), is(value));
+    }
+
+    /**
+     * Validates root data node.
+     *
+     * @param resourceData resource data which holds data node
+     * @return root data node
+     */
+    private static DataNode validateRootDataNode(ResourceData resourceData) {
+        List<DataNode> dataNodes = resourceData.dataNodes();
+        DataNode rootNode = dataNodes.get(0);
+        SchemaId rootSchemaId = rootNode.key().schemaId();
+        assertThat(rootSchemaId.name(), is("/"));
+        return rootNode;
+    }
+
+    /**
+     * Reads XML contents from file path and returns input stream.
+     *
+     * @param path path of XML file
+     * @return input stream
+     */
+    private static InputStream parseInput(String path) {
+        String temp;
+        StringBuilder sb = new StringBuilder();
+        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
+            while ((temp = br.readLine()) != null) {
+                sb.append(temp);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return IOUtils.toInputStream(sb);
+    }
+
+    /**
+     * Reads XML contents from file path and returns input stream.
+     *
+     * @param path path of XML file
+     * @return input stream
+     */
+    private static String parseXml(String path) {
+        String temp;
+        StringBuilder sb = new StringBuilder();
+        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
+            while ((temp = br.readLine()) != null) {
+                sb.append(temp);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Converts input stream to string format.
+     *
+     * @param inputStream input stream of xml
+     * @return XML string
+     */
+    private static String convertInputStreamToString(InputStream inputStream) {
+        BufferedReader br;
+        StringBuilder sb = new StringBuilder();
+        String xmlData;
+        br = new BufferedReader(new InputStreamReader(inputStream));
+        try {
+            while ((xmlData = br.readLine()) != null) {
+                sb.append(xmlData);
+            }
+        } catch (IOException e) {
+            throw new XmlSerializerException(e.getMessage());
+        }
+        return sb.toString();
+    }
+}
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/package-info.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/package-info.java
new file mode 100644
index 0000000..43b4abc
--- /dev/null
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/package-info.java
@@ -0,0 +1,20 @@
+/*
+ *  Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The XML serializer implementation of the YangSerializer interface.
+ */
+package org.onosproject.yang.serializers.xml;
diff --git a/serializers/xml/src/test/resources/testAugment.xml b/serializers/xml/src/test/resources/testAugment.xml
new file mode 100644
index 0000000..4c883f6
--- /dev/null
+++ b/serializers/xml/src/test/resources/testAugment.xml
@@ -0,0 +1,3 @@
+<t-point xmlns="urn:ietf:params:xml:ns:yang:yrt-ietf-network-topology">
+<tp-id>Stub</tp-id>
+</t-point>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testChoiceCase.xml b/serializers/xml/src/test/resources/testChoiceCase.xml
new file mode 100644
index 0000000..22590a1
--- /dev/null
+++ b/serializers/xml/src/test/resources/testChoiceCase.xml
@@ -0,0 +1,6 @@
+<banana xmlns="yrt:choice-case">
+<l1>value2</l1>
+</banana>
+<cold-drink xmlns="yrt:choice-case">
+<flavor>value3</flavor>
+</cold-drink>
diff --git a/serializers/xml/src/test/resources/testContainer.xml b/serializers/xml/src/test/resources/testContainer.xml
new file mode 100644
index 0000000..ee679b8
--- /dev/null
+++ b/serializers/xml/src/test/resources/testContainer.xml
@@ -0,0 +1,8 @@
+<food xmlns="yrt:food">
+<p1>p1_value</p1>
+<p2>p2_value</p2>
+<p2>p2_value1</p2>
+</food>
+<c2 xmlns="yrt:food">
+<p3>p3_value</p3>
+</c2>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testGroupingUses.xml b/serializers/xml/src/test/resources/testGroupingUses.xml
new file mode 100644
index 0000000..45d3d05
--- /dev/null
+++ b/serializers/xml/src/test/resources/testGroupingUses.xml
@@ -0,0 +1,2 @@
+<network-ref xmlns="urn:ietf:params:xml:ns:yang:yrt-ietf-network">abc
+</network-ref>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testListWithKeyleaves.xml b/serializers/xml/src/test/resources/testListWithKeyleaves.xml
new file mode 100644
index 0000000..1f9616a
--- /dev/null
+++ b/serializers/xml/src/test/resources/testListWithKeyleaves.xml
@@ -0,0 +1,16 @@
+<l1 xmlns="yrt:list" operation="replace">
+<k1>k1_Value</k1>
+<k2>k2_Value</k2>
+<k3>k3_Value</k3>
+<c1>
+<leaf_c1>l1_value</leaf_c1>
+</c1>
+</l1>
+<l1 xmlns="yrt:list" operation="replace">
+<k1>k1_Value1</k1>
+<k2>k2_Value2</k2>
+<k3>k3_Value3</k3>
+<c1>
+<leaf_c1>l1_value1</leaf_c1>
+</c1>
+</l1>
diff --git a/serializers/xml/src/test/resources/testModuleLevelLeaf.xml b/serializers/xml/src/test/resources/testModuleLevelLeaf.xml
new file mode 100644
index 0000000..13da6e6
--- /dev/null
+++ b/serializers/xml/src/test/resources/testModuleLevelLeaf.xml
@@ -0,0 +1,2 @@
+<bool xmlns="yrt:food">true</bool>
+<boolean xmlns="yrt:food">true</boolean>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testMultipleLevelAugment.xml b/serializers/xml/src/test/resources/testMultipleLevelAugment.xml
new file mode 100644
index 0000000..ab31d06
--- /dev/null
+++ b/serializers/xml/src/test/resources/testMultipleLevelAugment.xml
@@ -0,0 +1,6 @@
+<interface xmlns="ser.ospf" operation="replace">
+<area-type>Stub</area-type>
+</interface>
+<statistics xmlns="ser.ospf" operation="replace">
+<spf-runs-count>3</spf-runs-count>
+</statistics>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testXmlAttributes.xml b/serializers/xml/src/test/resources/testXmlAttributes.xml
new file mode 100644
index 0000000..0ca9a71
--- /dev/null
+++ b/serializers/xml/src/test/resources/testXmlAttributes.xml
@@ -0,0 +1,10 @@
+<top xmlns="http://example.com/schema/1.2/config">
+<interface xc:operation="replace">
+<name>Ethernet0/0</name>
+<mtu>1500</mtu>
+<address>
+<name>192.0.2.4</name>
+<prefix-length>24</prefix-length>
+</address>
+</interface>
+</top>
\ No newline at end of file