diff --git a/src/chain.c b/src/chain.c
index f01abb9..2a39985 100644
--- a/src/chain.c
+++ b/src/chain.c
@@ -689,37 +689,32 @@ int nft_mxml_chain_parse(mxml_node_t *tree, struct nft_chain *c,
 
 	name = nft_mxml_str_parse(tree, "name", MXML_DESCEND_FIRST,
 				  NFT_XML_MAND, err);
-	if (name == NULL)
-		return -1;
-	nft_chain_attr_set_str(c, NFT_CHAIN_ATTR_NAME, name);
+	if (name != NULL)
+		nft_chain_attr_set_str(c, NFT_CHAIN_ATTR_NAME, name);
 
 	if (nft_mxml_num_parse(tree, "handle", MXML_DESCEND_FIRST, BASE_DEC,
-			       &handle, NFT_TYPE_U64, NFT_XML_MAND, err) != 0)
-		return -1;
-	nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
+			       &handle, NFT_TYPE_U64, NFT_XML_MAND, err) == 0)
+		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
 
 	if (nft_mxml_num_parse(tree, "bytes", MXML_DESCEND_FIRST, BASE_DEC,
-			       &bytes, NFT_TYPE_U64, NFT_XML_MAND, err) != 0)
-		return -1;
-	nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES, bytes);
+			       &bytes, NFT_TYPE_U64, NFT_XML_MAND, err) == 0)
+		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES, bytes);
 
 
 	if (nft_mxml_num_parse(tree, "packets", MXML_DESCEND_FIRST, BASE_DEC,
-			       &packets, NFT_TYPE_U64, NFT_XML_MAND, err) != 0)
-		return -1;
-	nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS, packets);
+			       &packets, NFT_TYPE_U64, NFT_XML_MAND, err) == 0)
+		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS, packets);
 
 	table = nft_mxml_str_parse(tree, "table", MXML_DESCEND_FIRST,
 				   NFT_XML_MAND, err);
-	if (table == NULL)
-		return -1;
-	nft_chain_attr_set_str(c, NFT_CHAIN_ATTR_TABLE, table);
+
+	if (table != NULL)
+		nft_chain_attr_set_str(c, NFT_CHAIN_ATTR_TABLE, table);
 
 	family = nft_mxml_family_parse(tree, "family", MXML_DESCEND_FIRST,
 				       NFT_XML_MAND, err);
-	if (family < 0)
-		return -1;
-	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_FAMILY, family);
+	if (family >= 0)
+		nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_FAMILY, family);
 
 	hooknum_str = nft_mxml_str_parse(tree, "hooknum", MXML_DESCEND_FIRST,
 					 NFT_XML_OPT, err);
@@ -731,29 +726,28 @@ int nft_mxml_chain_parse(mxml_node_t *tree, struct nft_chain *c,
 
 		type = nft_mxml_str_parse(tree, "type", MXML_DESCEND_FIRST,
 					  NFT_XML_MAND, err);
-		if (type == NULL)
-			return -1;
-		nft_chain_attr_set_str(c, NFT_CHAIN_ATTR_TYPE, type);
+
+		if (type != NULL)
+			nft_chain_attr_set_str(c, NFT_CHAIN_ATTR_TYPE, type);
 
 		if (nft_mxml_num_parse(tree, "prio", MXML_DESCEND, BASE_DEC,
 				       &prio, NFT_TYPE_S32, NFT_XML_MAND,
-				       err) != 0)
-			return -1;
-		nft_chain_attr_set_s32(c, NFT_CHAIN_ATTR_PRIO, prio);
+				       err) == 0)
+			nft_chain_attr_set_s32(c, NFT_CHAIN_ATTR_PRIO, prio);
 
 		policy_str = nft_mxml_str_parse(tree, "policy",
 						MXML_DESCEND_FIRST,
 						NFT_XML_MAND, err);
-		if (policy_str == NULL)
-			return -1;
-
-		if (nft_str2verdict(policy_str, &policy) != 0) {
-			errno = EINVAL;
-			err->node_name = "policy";
-			err->error = NFT_PARSE_EBADTYPE;
-			return -1;
+		if (policy_str != NULL) {
+			if (nft_str2verdict(policy_str, &policy) != 0) {
+				errno = EINVAL;
+				err->node_name = "policy";
+				err->error = NFT_PARSE_EBADTYPE;
+				return -1;
+			}
+			nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY,
+					       policy);
 		}
-		nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy);
 	}
 
 	return 0;
@@ -858,25 +852,66 @@ static int nft_chain_snprintf_xml(char *buf, size_t size, struct nft_chain *c)
 {
 	int ret, len = size, offset = 0;
 
-	ret = snprintf(buf, len, "<chain><name>%s</name>"
-		       "<handle>%"PRIu64"</handle><bytes>%"PRIu64"</bytes>"
-		       "<packets>%"PRIu64"</packets><table>%s</table>",
-		       c->name, c->handle, c->bytes, c->packets, c->table);
+	ret = snprintf(buf, len, "<chain>");
 	SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 
+	if (c->flags & (1 << NFT_CHAIN_ATTR_NAME)) {
+		ret = snprintf(buf + offset, len, "<name>%s</name>", c->name);
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+	}
+	if (c->flags & (1 << NFT_CHAIN_ATTR_HANDLE)) {
+		ret = snprintf(buf + offset, len, "<handle>%"PRIu64"</handle>",
+			       c->handle);
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+	}
+	if (c->flags & (1 << NFT_CHAIN_ATTR_BYTES)) {
+		ret = snprintf(buf + offset, len, "<bytes>%"PRIu64"</bytes>",
+			       c->bytes);
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+	}
+	if (c->flags & (1 << NFT_CHAIN_ATTR_PACKETS)) {
+		ret = snprintf(buf + offset, len, "<packets>%"PRIu64"</packets>",
+			       c->packets);
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+	}
+	if (c->flags & (1 << NFT_CHAIN_ATTR_TABLE)) {
+		ret = snprintf(buf + offset, len, "<table>%s</table>",
+			       c->table);
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+	}
+	if (c->flags & (1 << NFT_CHAIN_ATTR_USE)) {
+		ret = snprintf(buf + offset, len, "<use>%u</use>", c->use);
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+	}
 	if (c->flags & (1 << NFT_CHAIN_ATTR_HOOKNUM)) {
-		ret =  snprintf(buf+offset, len,
-				"<type>%s</type>"
-				"<hooknum>%s</hooknum>"
-				"<prio>%d</prio>"
-				"<policy>%s</policy>",
-			c->type, nft_hooknum2str(c->family, c->hooknum),
-			c->prio, nft_verdict2str(c->policy));
+		if (c->flags & (1 << NFT_CHAIN_ATTR_TYPE)) {
+			ret = snprintf(buf + offset, len, "<type>%s</type>",
+				       c->type);
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+		}
+
+		ret = snprintf(buf + offset, len, "<hooknum>%s</hooknum>",
+			       nft_hooknum2str(c->family, c->hooknum));
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+		if (c->flags & (1 << NFT_CHAIN_ATTR_PRIO)) {
+			ret = snprintf(buf + offset, len, "<prio>%d</prio>",
+				       c->prio);
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+		}
+		if (c->flags & (1 << NFT_CHAIN_ATTR_POLICY)) {
+			ret = snprintf(buf + offset, len, "<policy>%s</policy>",
+				       nft_verdict2str(c->policy));
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+		}
+	}
+	if (c->flags & (1 << NFT_CHAIN_ATTR_FAMILY)) {
+		ret = snprintf(buf + offset, len, "<family>%s</family>",
+			       nft_family2str(c->family));
 		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 	}
 
-	ret = snprintf(buf+offset, len, "<family>%s</family></chain>",
-		       nft_family2str(c->family));
+	ret = snprintf(buf + offset, len, "</chain>");
 	SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 
 	return offset;
