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

Change-Id: Idffda88938d9c6c7b7c7814127a340bd2dc35039
diff --git a/model/src/main/java/org/onosproject/yang/model/ResourceId.java b/model/src/main/java/org/onosproject/yang/model/ResourceId.java
index c873cb1..a3bffaa 100644
--- a/model/src/main/java/org/onosproject/yang/model/ResourceId.java
+++ b/model/src/main/java/org/onosproject/yang/model/ResourceId.java
@@ -20,11 +20,9 @@
 import java.util.List;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
 import static java.util.Objects.hash;
 import static org.onosproject.yang.model.ModelConstants.LEAF_IS_TERMINAL;
 import static org.onosproject.yang.model.ModelConstants.NON_KEY_LEAF;
-import static org.onosproject.yang.model.ModelConstants.NO_KEY_SET;
 
 /**
  * Representation of an entity which identifies a resource in the logical tree
@@ -234,12 +232,24 @@
          * @return built resource identifier
          */
         public ResourceId build() {
-            checkNotNull(curKeyBuilder, NO_KEY_SET);
-            nodeKeyList.add(curKeyBuilder.build());
+            if (curKeyBuilder != null) {
+                nodeKeyList.add(curKeyBuilder.build());
+                curKeyBuilder = null;
+            }
             return new ResourceId(this);
         }
 
         /**
+         * Removes last key in the node key list.
+         *
+         * @return updated builder
+         */
+        public Builder removeLastKey() {
+            nodeKeyList.remove(nodeKeyList.size() - 1);
+            return this;
+        }
+
+        /**
          * Returns application information. This enables application to use
          * this builder as there work bench.
          *
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/DefaultAnnotation.java b/runtime/src/main/java/org/onosproject/yang/runtime/DefaultAnnotation.java
index 9c011e7..0f75340 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/DefaultAnnotation.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/DefaultAnnotation.java
@@ -35,7 +35,7 @@
      * @param n annotation name
      * @param v annotation value
      */
-    protected DefaultAnnotation(String n, String v) {
+    public DefaultAnnotation(String n, String v) {
         name = n;
         value = v;
     }
diff --git a/runtime/src/test/resources/schemaProviderTestYangFiles/food.yang b/runtime/src/test/resources/schemaProviderTestYangFiles/food.yang
index b340438..4c87fa0 100644
--- a/runtime/src/test/resources/schemaProviderTestYangFiles/food.yang
+++ b/runtime/src/test/resources/schemaProviderTestYangFiles/food.yang
@@ -17,7 +17,6 @@
     container food {
        choice snack {
            case sportsarena {
-
                leaf pretzel {
                    type empty;
                }
@@ -44,6 +43,18 @@
                }
            }
        }
+       leaf p1 {
+           type string;
+       }
+       leaf-list p2 {
+           type string;
+       }
+    }
+
+    container c2 {
+        leaf p3 {
+            type string;
+        }
     }
 
     leaf bool {
diff --git a/runtime/src/test/resources/xmlAttributes.yang b/runtime/src/test/resources/xmlAttributes.yang
new file mode 100644
index 0000000..f9f3f93
--- /dev/null
+++ b/runtime/src/test/resources/xmlAttributes.yang
@@ -0,0 +1,23 @@
+module attributes {
+    yang-version 1;
+    namespace "http://example.com/schema/1.2/config";
+    prefix "attr";
+    container top {
+        container interface {
+            leaf name {
+                type string;
+            }
+            leaf mtu {
+                type string;
+            }
+            container address {
+                leaf name {
+                    type string;
+                }
+                leaf prefix-length {
+                    type string;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/serializers/json/pom.xml b/serializers/json/pom.xml
index 7a9fc74..e512f8a 100644
--- a/serializers/json/pom.xml
+++ b/serializers/json/pom.xml
@@ -60,6 +60,11 @@
             <artifactId>jackson-annotations</artifactId>
             <version>2.8.6</version>
         </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-serializers-utils</artifactId>
+            <version>1.12-SNAPSHOT</version>
+        </dependency>
         <!-- TODO: remove
         <dependency>
             <groupId>org.onosproject</groupId>
diff --git a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DecoderUtils.java b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DecoderUtils.java
index 753b699..1e91cd7 100644
--- a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DecoderUtils.java
+++ b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DecoderUtils.java
@@ -17,66 +17,22 @@
 package org.onosproject.yang.serializers.json;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Lists;
 import org.onosproject.yang.model.DataNode;
 import org.onosproject.yang.model.ResourceId;
 import org.onosproject.yang.runtime.YangSerializerContext;
 import org.onosproject.yang.runtime.helperutils.SerializerHelper;
 
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
 
 /**
  * Utilities for parsing URI and JSON strings.
  */
 public final class DecoderUtils {
-    private static final Splitter SLASH_SPLITTER = Splitter.on('/');
-    private static final Splitter COMMA_SPLITTER = Splitter.on(',');
-    private static final String EQUAL = "=";
-    private static final String COMMA = ",";
-    private static final String COLON = ":";
-    private static final String SLASH = "/";
-    private static final String URI_ENCODING_CHAR_SET = "ISO-8859-1";
-    private static final String ERROR_LIST_MSG = "List/Leaf-list node should be " +
-            "in format \"nodeName=key\"or \"nodeName=instance-value\"";
-
 
     // no instantiation
     private DecoderUtils() {
     }
 
     /**
-     * Converts a URI string to resource identifier.
-     *
-     * @param uriString given URI
-     * @param context   YANG schema context information
-     * @return resource ID
-     */
-    public static ResourceId convertUriToRid(String uriString,
-                                             YangSerializerContext context) {
-        if (uriString == null || uriString.isEmpty()) {
-            return null;
-        }
-
-        List<String> paths = urlPathArgsDecode(SLASH_SPLITTER.split(uriString));
-
-        if (!paths.isEmpty()) {
-            ResourceId.Builder ridBuilder =
-                    SerializerHelper.initializeResourceId(context);
-            processPathSegments(paths, ridBuilder);
-            return ridBuilder.build();
-        }
-
-        return null;
-    }
-
-    /**
      * Converts JSON data to a data node. This method should be used when
      * the URI corresponding to the JSON body is null (Thus the caller can
      * only provide a serializer context rather than a resource ID).
@@ -125,157 +81,4 @@
 
         return dataNodeBuilder.build();
     }
-
-    /**
-     * Converts a list of path from the original format to ISO-8859-1 code.
-     *
-     * @param paths the original paths
-     * @return list of decoded paths
-     */
-    public static List<String> urlPathArgsDecode(Iterable<String> paths) {
-        try {
-            List<String> decodedPathArgs = new ArrayList<>();
-            for (String pathArg : paths) {
-                String decode = URLDecoder.decode(pathArg,
-                                                  URI_ENCODING_CHAR_SET);
-                decodedPathArgs.add(decode);
-            }
-            return decodedPathArgs;
-        } catch (UnsupportedEncodingException e) {
-            throw new SerializerException("Invalid URL path arg '" +
-                                                  paths + "': ", e);
-        }
-    }
-
-    private static ResourceId.Builder processPathSegments(List<String> paths,
-                                                          ResourceId.Builder builder) {
-        if (paths.isEmpty()) {
-            return builder;
-        }
-
-        boolean isLastSegment = paths.size() == 1;
-
-        String segment = paths.iterator().next();
-        processSinglePathSegment(segment, builder);
-
-        if (isLastSegment) {
-            // We have hit the base case of recursion.
-            return builder;
-        }
-
-        /*
-         * Chop off the first segment, and recursively process the rest
-         * of the path segments.
-         */
-        List<String> remainPaths = paths.subList(1, paths.size());
-        processPathSegments(remainPaths, builder);
-
-        return builder;
-    }
-
-    private static void processSinglePathSegment(String pathSegment,
-                                                 ResourceId.Builder builder) {
-        if (pathSegment.contains(COLON)) {
-            processPathSegmentWithNamespace(pathSegment, builder);
-        } else {
-            processPathSegmentWithoutNamespace(pathSegment, builder);
-        }
-    }
-
-    private static void processPathSegmentWithNamespace(String pathSegment,
-                                                        ResourceId.Builder builder) {
-
-        String nodeName = getLatterSegment(pathSegment, COLON);
-        String namespace = getPreSegment(pathSegment, COLON);
-        addNodeNameToRid(nodeName, namespace, builder);
-    }
-
-    private static void processPathSegmentWithoutNamespace(String nodeName,
-                                                           ResourceId.Builder builder) {
-        addNodeNameToRid(nodeName, null, builder);
-    }
-
-    private static void addNodeNameToRid(String nodeName,
-                                         String namespace,
-                                         ResourceId.Builder builder) {
-        if (nodeName.contains(EQUAL)) {
-            addListOrLeafList(nodeName, namespace, builder);
-        } else {
-            addLeaf(nodeName, namespace, builder);
-        }
-    }
-
-    private static void addListOrLeafList(String path,
-                                          String namespace,
-                                          ResourceId.Builder builder) {
-        String nodeName = getPreSegment(path, EQUAL);
-        String keyStr = getLatterSegment(path, EQUAL);
-        if (keyStr == null) {
-            throw new SerializerException(ERROR_LIST_MSG);
-        }
-
-        if (keyStr.contains(COMMA)) {
-            List<String> keys = Lists.
-                    newArrayList(COMMA_SPLITTER.split(keyStr));
-            SerializerHelper.addToResourceId(builder, nodeName, namespace, keys);
-        } else {
-            SerializerHelper.addToResourceId(builder, nodeName, namespace,
-                                             Lists.newArrayList(keyStr));
-        }
-    }
-
-    private static void addLeaf(String nodeName,
-                                String namespace,
-                                ResourceId.Builder builder) {
-        checkNotNull(nodeName);
-        SerializerHelper.addToResourceId(builder, nodeName, namespace, "");
-    }
-
-    /**
-     * Returns the previous segment of a path which is separated by a split char.
-     * For example:
-     * <pre>
-     * "foo:bar", ":"   -->  "foo"
-     * </pre>
-     *
-     * @param path      the original path string
-     * @param splitChar char used to split the path
-     * @return the previous segment of the path
-     */
-    private static String getPreSegment(String path, String splitChar) {
-        int idx = path.indexOf(splitChar);
-        if (idx == -1) {
-            return null;
-        }
-
-        if (path.indexOf(splitChar, idx + 1) != -1) {
-            return null;
-        }
-
-        return path.substring(0, idx);
-    }
-
-    /**
-     * Returns the latter segment of a path which is separated by a split char.
-     * For example:
-     * <pre>
-     * "foo:bar", ":"   -->  "bar"
-     * </pre>
-     *
-     * @param path      the original path string
-     * @param splitChar char used to split the path
-     * @return the latter segment of the path
-     */
-    private static String getLatterSegment(String path, String splitChar) {
-        int idx = path.indexOf(splitChar);
-        if (idx == -1) {
-            return path;
-        }
-
-        if (path.indexOf(splitChar, idx + 1) != -1) {
-            return null;
-        }
-
-        return path.substring(idx + 1);
-    }
 }
diff --git a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/EncoderUtils.java b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/EncoderUtils.java
index 00022e5..c0e7ccc 100644
--- a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/EncoderUtils.java
+++ b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/EncoderUtils.java
@@ -17,17 +17,11 @@
 package org.onosproject.yang.serializers.json;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.base.Splitter;
 import org.onosproject.yang.model.DataNode;
 import org.onosproject.yang.model.InnerNode;
-import org.onosproject.yang.model.KeyLeaf;
-import org.onosproject.yang.model.LeafListKey;
-import org.onosproject.yang.model.ListKey;
 import org.onosproject.yang.model.NodeKey;
-import org.onosproject.yang.model.ResourceId;
 
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -45,98 +39,12 @@
  * Utilities for converting Data Nodes into JSON format.
  */
 public final class EncoderUtils {
-    private static final Splitter SLASH_SPLITTER = Splitter.on('/');
-    private static final Splitter COMMA_SPLITTER = Splitter.on(',');
-    private static final String EQUAL = "=";
-    private static final String COMMA = ",";
-    private static final String COLON = ":";
-    private static final String SLASH = "/";
 
     // no instantiation
     private EncoderUtils() {
     }
 
     /**
-     * Converts a resource identifier to URI string.
-     *
-     * @param rid resource identifier
-     * @return URI
-     */
-    public static String convertRidToUri(ResourceId rid) {
-        if (rid == null) {
-            return null;
-        }
-
-        StringBuilder uriBuilder = new StringBuilder();
-        List<NodeKey> nodeKeyList = rid.nodeKeys();
-        String curNameSpace = null;
-        for (NodeKey key : nodeKeyList) {
-            curNameSpace = addNodeKeyToUri(key, curNameSpace, uriBuilder);
-        }
-        return uriBuilder.toString();
-    }
-
-    private static String addNodeKeyToUri(NodeKey key,
-                                          String curNameSpace,
-                                          StringBuilder uriBuilder) {
-        String newNameSpace;
-        if (key instanceof LeafListKey) {
-            newNameSpace = addLeafListNodeToUri((LeafListKey) key, curNameSpace, uriBuilder);
-        } else if (key instanceof ListKey) {
-            newNameSpace = addListNodeToUri((ListKey) key, curNameSpace, uriBuilder);
-        } else {
-            uriBuilder.append(SLASH);
-            newNameSpace = addNodeNameToUri(key, curNameSpace, uriBuilder);
-        }
-        return newNameSpace;
-    }
-
-    private static String addLeafListNodeToUri(LeafListKey key,
-                                               String curNameSpace,
-                                               StringBuilder uriBuilder) {
-
-        String newNameSpace = addNodeNameToUri(key, curNameSpace, uriBuilder);
-        uriBuilder.append(EQUAL);
-        uriBuilder.append(key.asString());
-        return newNameSpace;
-    }
-
-    private static String addListNodeToUri(ListKey key,
-                                           String curNameSpace,
-                                           StringBuilder uriBuilder) {
-        String newNameSpace = addNodeNameToUri(key, curNameSpace, uriBuilder);
-        uriBuilder.append(EQUAL);
-        String prefix = "";
-        for (KeyLeaf keyLeaf : key.keyLeafs()) {
-            uriBuilder.append(prefix);
-            prefix = COMMA;
-            uriBuilder.append(keyLeaf.leafValue().toString());
-        }
-
-        return newNameSpace;
-    }
-
-    private static String addNodeNameToUri(NodeKey key,
-                                           String curNameSpace,
-                                           StringBuilder uriBuilder) {
-        String nodeName = key.schemaId().name();
-        String newNameSpace = key.schemaId().namespace();
-
-        uriBuilder.append(nodeName);
-
-        if (newNameSpace == null) {
-            return curNameSpace;
-        }
-
-        if (!newNameSpace.equals(curNameSpace)) {
-            uriBuilder.append(COLON);
-            uriBuilder.append(newNameSpace);
-        }
-
-        return newNameSpace;
-    }
-
-    /**
      * Converts a data node to JSON data.
      *
      * @param dataNode given data node
diff --git a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/JsonSerializer.java b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/JsonSerializer.java
index f635a50..40608b7 100644
--- a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/JsonSerializer.java
+++ b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/JsonSerializer.java
@@ -37,9 +37,9 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onosproject.yang.serializers.json.DecoderUtils.convertJsonToDataNode;
-import static org.onosproject.yang.serializers.json.DecoderUtils.convertUriToRid;
 import static org.onosproject.yang.serializers.json.EncoderUtils.convertDataNodeToJson;
-import static org.onosproject.yang.serializers.json.EncoderUtils.convertRidToUri;
+import static org.onosproject.yang.serializers.utils.SerializersUtil.convertRidToUri;
+import static org.onosproject.yang.serializers.utils.SerializersUtil.convertUriToRid;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -64,8 +64,8 @@
     public CompositeData decode(CompositeStream compositeStream,
                                 YangSerializerContext yangSerializerContext) {
         try {
-            ResourceId rid = convertUriToRid(compositeStream.resourceId(),
-                                             yangSerializerContext);
+            ResourceId.Builder rIdBuilder = convertUriToRid(
+                    compositeStream.resourceId(), yangSerializerContext);
 
             ObjectNode rootNode = null;
 
@@ -83,9 +83,9 @@
              * and in this case the resourceId builder which was constructed
              * for a URL, needs to be given as an Input parameter.
              */
-            if (rid != null) {
+            if (rIdBuilder != null) {
                 dataNode = convertJsonToDataNode(rootNode,
-                                                 new ResourceId.Builder(rid));
+                                                 rIdBuilder);
 
             } else {
                 dataNode = convertJsonToDataNode(rootNode,
@@ -93,13 +93,8 @@
             }
 
             ResourceData resourceData = DefaultResourceData.builder().
-                    addDataNode(dataNode).resourceId(rid).build();
+                    addDataNode(dataNode).resourceId(rIdBuilder.build()).build();
             return DefaultCompositeData.builder().resourceData(resourceData).build();
-        } catch (CloneNotSupportedException e) {
-            log.error("ERROR: JsonProcessingException {}",
-                      e.getMessage());
-            log.debug("Exception in decode:", e);
-            throw new SerializerException("JSON serializer decode failure");
         } catch (JsonProcessingException e) {
             log.error("ERROR: JsonProcessingException {}",
                       e.getMessage());
diff --git a/serializers/pom.xml b/serializers/pom.xml
index 6846261..1740256 100644
--- a/serializers/pom.xml
+++ b/serializers/pom.xml
@@ -31,6 +31,8 @@
 
     <modules>
         <module>json</module>
+        <module>xml</module>
+        <module>utils</module>
     </modules>
 
     <description>Serializers for various codecs</description>
diff --git a/serializers/utils/pom.xml b/serializers/utils/pom.xml
new file mode 100644
index 0000000..b1866f9
--- /dev/null
+++ b/serializers/utils/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-yang-serializers</artifactId>
+        <version>1.12-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>onos-yang-serializers-utils</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-runtime</artifactId>
+            <version>1.12-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.servicemix.bundles</groupId>
+            <artifactId>org.apache.servicemix.bundles.dom4j</artifactId>
+            <version>1.6.1_5</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.0.2</version>
+                <configuration>
+                    <skipIfEmpty>true</skipIfEmpty>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>default</id>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/SerializerUtilException.java b/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/SerializerUtilException.java
new file mode 100644
index 0000000..eef46dc
--- /dev/null
+++ b/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/SerializerUtilException.java
@@ -0,0 +1,43 @@
+/*
+ *  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.utils;
+
+/**
+ * Represents class of errors related to serializer utils.
+ */
+public class SerializerUtilException extends RuntimeException {
+
+    /**
+     * Constructs an exception with the specified message.
+     *
+     * @param message the message describing the specific nature of the error
+     */
+    public SerializerUtilException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs an exception with the specified message and the underlying
+     * cause.
+     *
+     * @param message the message describing the specific nature of the error
+     * @param cause   the underlying cause of this error
+     */
+    public SerializerUtilException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/SerializersUtil.java b/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/SerializersUtil.java
new file mode 100644
index 0000000..dbb0222
--- /dev/null
+++ b/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/SerializersUtil.java
@@ -0,0 +1,378 @@
+/*
+ *  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.utils;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import org.dom4j.Attribute;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.onosproject.yang.model.KeyLeaf;
+import org.onosproject.yang.model.LeafListKey;
+import org.onosproject.yang.model.ListKey;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.Annotation;
+import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
+import org.onosproject.yang.runtime.DefaultAnnotation;
+import org.onosproject.yang.runtime.YangSerializerContext;
+import org.onosproject.yang.runtime.helperutils.SerializerHelper;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Utilities for serializers.
+ */
+public final class SerializersUtil {
+    private static final Splitter SLASH_SPLITTER = Splitter.on('/');
+    private static final Splitter COMMA_SPLITTER = Splitter.on(',');
+    private static final String QUOTES = "\"";
+    private static final String ROOT_ELEMENT_START = "<root ";
+    private static final String ROOT_ELEMENT_END = "</root>";
+    private static final String URI_ENCODING_CHAR_SET = "ISO-8859-1";
+    private static final String ERROR_LIST_MSG = "List/Leaf-list node should be " +
+            "in format \"nodeName=key\"or \"nodeName=instance-value\"";
+    private static final String EQUAL = "=";
+    private static final String COMMA = ",";
+    private static final String COLON = ":";
+    private static final String SLASH = "/";
+
+    // no instantiation
+    private SerializersUtil() {
+    }
+
+    /**
+     * Converts XML atrtibutes into annotated node info.
+     *
+     * @param element XML element
+     * @param id      resource id of an element
+     * @return annotated node info
+     */
+    public static AnnotatedNodeInfo convertXmlAttributesToAnnotations(Element element,
+                                                                      ResourceId id) {
+        Iterator iter = element.attributeIterator();
+        if (!iter.hasNext()) {
+            // element does not have any attributes
+            return null;
+        }
+        AnnotatedNodeInfo.Builder builder = DefaultAnnotatedNodeInfo.builder();
+        builder = builder.resourceId(id);
+        while (iter.hasNext()) {
+            Attribute attr = (Attribute) iter.next();
+            DefaultAnnotation annotation = new DefaultAnnotation(
+                    attr.getQualifiedName(), attr.getValue());
+            builder = builder.addAnnotation(annotation);
+        }
+        return builder.build();
+    }
+
+
+    /**
+     * Appends the XML data with root element.
+     *
+     * @param inputStream        XML data
+     * @param protocolAnnotation list of annoations for root element
+     * @return XML with root element
+     * @throws DocumentException if root element cannot be created
+     * @throws IOException       if input data cannot be read
+     */
+    public static String addRootElementWithAnnotation(InputStream inputStream,
+                                                      List<Annotation>
+                                                              protocolAnnotation)
+            throws DocumentException, IOException {
+        BufferedReader br;
+        StringBuilder sb = new StringBuilder();
+        String xmlData;
+        // Parse composite stream resourceData
+        br = new BufferedReader(new InputStreamReader(inputStream));
+        while ((xmlData = br.readLine()) != null) {
+            sb.append(xmlData);
+        }
+
+        StringBuilder rootElement = new StringBuilder(ROOT_ELEMENT_START);
+        if (protocolAnnotation != null) {
+            for (Annotation annotation : protocolAnnotation) {
+                rootElement.append(annotation.name()).append(EQUAL)
+                        .append(QUOTES).append(annotation.value()).append(QUOTES);
+            }
+        }
+        rootElement.append(">").append(sb.toString()).append(ROOT_ELEMENT_END);
+        return rootElement.toString();
+    }
+
+    /**
+     * Converts a URI string to resource identifier.
+     *
+     * @param uriString given URI
+     * @param context   YANG schema context information
+     * @return resource ID
+     */
+    public static ResourceId.Builder convertUriToRid(String uriString,
+                                                     YangSerializerContext context) {
+        if (uriString == null || uriString.isEmpty()) {
+            return null;
+        }
+
+        List<String> paths = urlPathArgsDecode(SLASH_SPLITTER.split(uriString));
+
+        if (!paths.isEmpty()) {
+            ResourceId.Builder ridBuilder =
+                    SerializerHelper.initializeResourceId(context);
+            processPathSegments(paths, ridBuilder);
+            return ridBuilder;
+        }
+
+        return null;
+    }
+
+    /**
+     * Converts a list of path from the original format to ISO-8859-1 code.
+     *
+     * @param paths the original paths
+     * @return list of decoded paths
+     */
+    public static List<String> urlPathArgsDecode(Iterable<String> paths) {
+        try {
+            List<String> decodedPathArgs = new ArrayList<>();
+            for (String pathArg : paths) {
+                String decode = URLDecoder.decode(pathArg,
+                                                  URI_ENCODING_CHAR_SET);
+                decodedPathArgs.add(decode);
+            }
+            return decodedPathArgs;
+        } catch (UnsupportedEncodingException e) {
+            throw new SerializerUtilException("Invalid URL path arg '" +
+                                                      paths + "': ", e);
+        }
+    }
+
+    private static ResourceId.Builder processPathSegments(List<String> paths,
+                                                          ResourceId.Builder builder) {
+        if (paths.isEmpty()) {
+            return builder;
+        }
+
+        boolean isLastSegment = paths.size() == 1;
+
+        String segment = paths.iterator().next();
+        processSinglePathSegment(segment, builder);
+
+        if (isLastSegment) {
+            // We have hit the base case of recursion.
+            return builder;
+        }
+
+        /*
+         * Chop off the first segment, and recursively process the rest
+         * of the path segments.
+         */
+        List<String> remainPaths = paths.subList(1, paths.size());
+        processPathSegments(remainPaths, builder);
+
+        return builder;
+    }
+
+    private static void processSinglePathSegment(String pathSegment,
+                                                 ResourceId.Builder builder) {
+        if (pathSegment.contains(COLON)) {
+            processPathSegmentWithNamespace(pathSegment, builder);
+        } else {
+            processPathSegmentWithoutNamespace(pathSegment, builder);
+        }
+    }
+
+    private static void processPathSegmentWithNamespace(String pathSegment,
+                                                        ResourceId.Builder builder) {
+
+        String nodeName = getLatterSegment(pathSegment, COLON);
+        String namespace = getPreSegment(pathSegment, COLON);
+        addNodeNameToRid(nodeName, namespace, builder);
+    }
+
+    private static void processPathSegmentWithoutNamespace(String nodeName,
+                                                           ResourceId.Builder builder) {
+        addNodeNameToRid(nodeName, null, builder);
+    }
+
+    private static void addNodeNameToRid(String nodeName,
+                                         String namespace,
+                                         ResourceId.Builder builder) {
+        if (nodeName.contains(EQUAL)) {
+            addListOrLeafList(nodeName, namespace, builder);
+        } else {
+            addLeaf(nodeName, namespace, builder);
+        }
+    }
+
+    private static void addListOrLeafList(String path,
+                                          String namespace,
+                                          ResourceId.Builder builder) {
+        String nodeName = getPreSegment(path, EQUAL);
+        String keyStr = getLatterSegment(path, EQUAL);
+        if (keyStr == null) {
+            throw new SerializerUtilException(ERROR_LIST_MSG);
+        }
+
+        if (keyStr.contains(COMMA)) {
+            List<String> keys = Lists.
+                    newArrayList(COMMA_SPLITTER.split(keyStr));
+            SerializerHelper.addToResourceId(builder, nodeName, namespace, keys);
+        } else {
+            SerializerHelper.addToResourceId(builder, nodeName, namespace,
+                                             Lists.newArrayList(keyStr));
+        }
+    }
+
+    private static void addLeaf(String nodeName,
+                                String namespace,
+                                ResourceId.Builder builder) {
+        checkNotNull(nodeName);
+        String value = null;
+        SerializerHelper.addToResourceId(builder, nodeName, namespace, value);
+    }
+
+    /**
+     * Returns the previous segment of a path which is separated by a split char.
+     * For example:
+     * <pre>
+     * "foo:bar", ":"   -->  "foo"
+     * </pre>
+     *
+     * @param path      the original path string
+     * @param splitChar char used to split the path
+     * @return the previous segment of the path
+     */
+    private static String getPreSegment(String path, String splitChar) {
+        int idx = path.lastIndexOf(splitChar);
+        if (idx == -1) {
+            return null;
+        }
+        return path.substring(0, idx);
+    }
+
+    /**
+     * Returns the latter segment of a path which is separated by a split char.
+     * For example:
+     * <pre>
+     * "foo:bar", ":"   -->  "bar"
+     * </pre>
+     *
+     * @param path      the original path string
+     * @param splitChar char used to split the path
+     * @return the latter segment of the path
+     */
+    private static String getLatterSegment(String path, String splitChar) {
+        int idx = path.lastIndexOf(splitChar);
+        if (idx == -1) {
+            return path;
+        }
+
+        return path.substring(idx + 1);
+    }
+
+    /**
+     * Converts a resource identifier to URI string.
+     *
+     * @param rid resource identifier
+     * @return URI
+     */
+    public static String convertRidToUri(ResourceId rid) {
+        if (rid == null) {
+            return null;
+        }
+
+        StringBuilder uriBuilder = new StringBuilder();
+        List<NodeKey> nodeKeyList = rid.nodeKeys();
+        String curNameSpace = null;
+        for (NodeKey key : nodeKeyList) {
+            curNameSpace = addNodeKeyToUri(key, curNameSpace, uriBuilder);
+        }
+        return uriBuilder.toString();
+    }
+
+    private static String addNodeKeyToUri(NodeKey key,
+                                          String curNameSpace,
+                                          StringBuilder uriBuilder) {
+        String newNameSpace;
+        if (key instanceof LeafListKey) {
+            newNameSpace = addLeafListNodeToUri((LeafListKey) key, curNameSpace, uriBuilder);
+        } else if (key instanceof ListKey) {
+            newNameSpace = addListNodeToUri((ListKey) key, curNameSpace, uriBuilder);
+        } else {
+            uriBuilder.append(SLASH);
+            newNameSpace = addNodeNameToUri(key, curNameSpace, uriBuilder);
+        }
+        return newNameSpace;
+    }
+
+    private static String addLeafListNodeToUri(LeafListKey key,
+                                               String curNameSpace,
+                                               StringBuilder uriBuilder) {
+
+        String newNameSpace = addNodeNameToUri(key, curNameSpace, uriBuilder);
+        uriBuilder.append(EQUAL);
+        uriBuilder.append(key.asString());
+        return newNameSpace;
+    }
+
+    private static String addListNodeToUri(ListKey key,
+                                           String curNameSpace,
+                                           StringBuilder uriBuilder) {
+        String newNameSpace = addNodeNameToUri(key, curNameSpace, uriBuilder);
+        uriBuilder.append(EQUAL);
+        String prefix = "";
+        for (KeyLeaf keyLeaf : key.keyLeafs()) {
+            uriBuilder.append(prefix);
+            prefix = COMMA;
+            uriBuilder.append(keyLeaf.leafValue().toString());
+        }
+
+        return newNameSpace;
+    }
+
+    private static String addNodeNameToUri(NodeKey key,
+                                           String curNameSpace,
+                                           StringBuilder uriBuilder) {
+        String nodeName = key.schemaId().name();
+        String newNameSpace = key.schemaId().namespace();
+
+        uriBuilder.append(nodeName);
+
+        if (newNameSpace == null) {
+            return curNameSpace;
+        }
+
+        if (!newNameSpace.equals(curNameSpace)) {
+            uriBuilder.append(COLON);
+            uriBuilder.append(newNameSpace);
+        }
+
+        return newNameSpace;
+    }
+
+}
diff --git a/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/package-info.java b/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/package-info.java
new file mode 100644
index 0000000..65d177b
--- /dev/null
+++ b/serializers/utils/src/main/java/org/onosproject/yang/serializers/utils/package-info.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+/**
+ * The XML codec implementation of the YangSerializer interface.
+ */
+package org.onosproject.yang.serializers.utils;
diff --git a/serializers/xml/pom.xml b/serializers/xml/pom.xml
new file mode 100644
index 0000000..d757e5b
--- /dev/null
+++ b/serializers/xml/pom.xml
@@ -0,0 +1,96 @@
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-yang-serializers</artifactId>
+        <version>1.12-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>onos-yang-serializers-xml</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.21</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-runtime</artifactId>
+            <version>1.12-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.servicemix.bundles</groupId>
+            <artifactId>org.apache.servicemix.bundles.dom4j</artifactId>
+            <version>1.6.1_5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-serializers-utils</artifactId>
+            <version>1.12-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>RELEASE</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.onosproject</groupId>
+                <artifactId>onos-yang-compiler-maven-plugin</artifactId>
+                <version>${project.version}</version>
+                <configuration>
+                    <yangFilesDir>src/test/resources</yangFilesDir>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>default</id>
+                        <goals>
+                            <goal>yang2java</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.0.2</version>
+                <configuration>
+                    <skipIfEmpty>true</skipIfEmpty>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>default</id>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
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