[Kimchi-devel] [PATCH 1/3] xml parser: Add a parser to xmlutils

lvroyce at linux.vnet.ibm.com lvroyce at linux.vnet.ibm.com
Thu Jan 9 10:32:53 UTC 2014


From: Royce Lv <lvroyce at linux.vnet.ibm.com>

Add an xml parser to xmlutils.py to deal with the increasing need
in kimchi to converse an xml to dict.

Signed-off-by: Bing Bu Cao <mars at linux.vnet.ibm.com>
Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
---
 src/kimchi/exception.py |  4 ++++
 src/kimchi/xmlutils.py  | 54 ++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/src/kimchi/exception.py b/src/kimchi/exception.py
index bff0a18..623e6b3 100644
--- a/src/kimchi/exception.py
+++ b/src/kimchi/exception.py
@@ -43,3 +43,7 @@ class InvalidOperation(Exception):
 
 class IsoFormatError(Exception):
     pass
+
+
+class ParseError(Exception):
+    pass
diff --git a/src/kimchi/xmlutils.py b/src/kimchi/xmlutils.py
index 51ff0ec..f94db30 100644
--- a/src/kimchi/xmlutils.py
+++ b/src/kimchi/xmlutils.py
@@ -23,7 +23,11 @@
 import libxml2
 
 
-from xml.etree import ElementTree
+from collections import defaultdict
+from xml.etree import ElementTree as ET
+
+
+from kimchi.exception import ParseError
 
 
 def xpath_get_text(xml, expr):
@@ -36,7 +40,51 @@ def xpath_get_text(xml, expr):
 
 
 def xml_item_update(xml, xpath, value):
-    root = ElementTree.fromstring(xml)
+    root = ET.fromstring(xml)
     item = root.find(xpath)
     item.text = value
-    return ElementTree.tostring(root, encoding="utf-8")
+    return ET.tostring(root, encoding="utf-8")
+
+
+def xml_to_dict(xml, fromstring=True):
+    try:
+        if fromstring:
+            t = ET.fromstring(xml)
+        else:
+            t = ET.parse(xml).getroot()
+    except ET.ParseError:
+            raise ParseError("XML parse failed, invalid XML file")
+    return _etree_to_dict(t)
+
+
+def _etree_to_dict(t):
+    # Convert an etree object to dict
+    d = {t.tag: {} if t.attrib else None}
+    children = list(t)
+    td = {}
+    if children:
+        dd = defaultdict(list)
+        #if has subelement, iteration as it's a new element
+        for dc in map(_etree_to_dict, children):
+            for k, v in dc.iteritems():
+                dd[k].append(v)
+                for k, v in dd.iteritems():
+                    if len(v) == 1:
+                        va = v[0]
+                    else:
+                        va = v
+                    td.update({k: va})
+                    d[t.tag] = td
+
+    #prepend '@' to attr and '#' to value
+    if t.attrib:
+        d[t.tag].update((k, v) for k, v in t.attrib.iteritems())
+    if t.text:
+        text = t.text.strip()
+        if children or t.attrib:
+            if text:
+                d[t.tag]['#value'] = text
+        else:
+            d[t.tag] = text
+
+    return d
-- 
1.8.1.2




More information about the Kimchi-devel mailing list